Точка перебігу
В імперативному програмуванні точка перебігу (англ. sequence point) визначає будь-яку точку виконання програми, в якій гарантовано, що всі побічні ефекти попередніх обчислень вже виконані й жоден з побічних ефектів наступних обчислень ще не відбувся. Вони часто згадуються стосовно C і C++, бо результат деяких виразів залежить від послідовності виконання підвиразів. Додання однієї або більше точок перебігу це спосіб забезпечення послідовного результату, бо так обмежується можливий порядок обчислень.
Уявімо дві функції f()
і g()
. В C і C++, оператор +
не пов'язується з точкою перебігу, отже в виразі f()+g()
можливо, що або f()
, або g()
виконається першою Оператор кома вводить точку перебігу, звідси в коді f(),g()
порядок обчислень: спочатку викликається f()
, а тоді g()
.
Точки перебігу вступають в гру коли одна й та сама змінна змінюється більше одного разу в одному виразі. Часто згадуваний приклад це С-вираз i=i++
. Кінцеве значення i
неоднозначне, бо, залежно від порядку обчислення, інкремент може вібутися до, після або паралельно з присвоєнням. Певна мова може визначати один з можливих способів поведінки або сказати, що поведінка невизначена. В C і C++, обчислення таких виразів породжує невизначену поведінку.[1] У долішній заувазі стандарт вказує приклади виразів, які викличуть двозначність:
i = ++i + 1;
a[i++] = i;
а ці дозволені:
i = i + 1;
a[i] = i;
В C[2] і C++,[3] точки перебігу зустрічаються в таких місцях. (В C++, перевантаження операторів так само як і функції, отже перевантажені оператори вводять точки перебігу так само як і виклики функцій.)
- Між обчисленням лівих і правих операндів && (логічний AND), || (логічний OR), і оператора кома. Наприклад, у виразі
*p++ != 0 && *q++ != 0
, всі побічні ефекти підвиразу*p++ != 0
завершуються до спроби доступу доq
. - Між обчисленням першого операнда тримісного умовного оператора й другим або третім оператором. Наприклад, у виразі
a = (*p++) ? (*p++) : 0
присутня точка перебігу між першим*p++
, тобто значення буде збільшено до часу як другий операнд буде виконано. - Наприкінці повного виразу. Ця категорія охоплює вирази інструкції (такі як надавання значення
a=b;
), інструкції повернення, керувальні виразиif
,switch
,while
або виразиdo
-while
, і всі три вирази в коді виразуfor
. - Перед входом у викликану функцію. Порядок обчислення аргументів не визначається, але ця точка перебігу значить, що всі їхні побічні ефекти завершуються до входу в функцію. У виразі
f(i++) + g(j++) + h(k++)
,f
викликається із початковим значеннямi
, алеi
збільшується до входу вf
. Схожим чином,j
іk
оновлюються перед входом уg
іh
відповідно. Однак, не вказано ні в якому порядку викликаютьсяf()
,g()
,h()
, ні в якому порядку збільшуютьсяi
,j
,k
. Змінніj
іk
в тіліf
можуть бути, а можуть не бути збільшеними. Зауважте, що викликf(a,b,c)
це не використання оператора коми і порядок обчисленняa
,b
іc
невизначений. - Коли відбувається повернення з функції, після того як значення до повернення копіюється в викликальний контекст. (Ця точка перебігу визначена лиш стандарті С++; вона тільки неявно присутня в C.[4])
- По завершені ініціалізатора; наприклад, після завершення обчислення
5
в оголошенніint a = 5;
.
- ↑ Пункт 6.5#2 специфікації C99: "Між попередньою й наступною точкою перебігу значення збережене в об'єкті має змінитися через обчислення виразу не більше одного разу. Далі більше, доступ до попереднього значення може бути надано лише для визначення значення, що буде збережене."
- ↑ Додаток до специфікації C99 перелічує обставини за яких можуть бути присутні точкі перебігу.
- ↑ Стандарт С++ 1998 перелічує точки перебігу в розділі 1.9, параграфи 16–18.
- ↑ Стандарт C++, ISO 14882:2003, розділ 1.9, долішня заувага 11.
Це незавершена стаття про програмування. Ви можете допомогти проєкту, виправивши або дописавши її. |