Точка перебігу
В імперативному програмуванні точка перебігу (англ. 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 і C++ [ред.]
В 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.
