Точка перебігу

В імперативному програмуванні точка перебігу (англ. 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++, перевантаження операторів так само як і функції, отже перевантажені оператори вводять точки перебігу так само як і виклики функцій.)

  1. Між обчисленням лівих і правих операндів && (логічний AND), || (логічний OR), і оператора кома. Наприклад, у виразі *p++ != 0 && *q++ != 0, всі побічні ефекти підвиразу *p++ != 0 завершуються до спроби доступу до q.
  2. Між обчисленням першого операнда тримісного умовного оператора й другим або третім оператором. Наприклад, у виразі a = (*p++) ? (*p++) : 0 присутня точка перебігу між першим *p++, тобто значення буде збільшено до часу як другий операнд буде виконано.
  3. Наприкінці повного виразу. Ця категорія охоплює вирази інструкції (такі як надавання значення a=b;), інструкції повернення, керувальні вирази if, switch, while або вирази do-while, і всі три вирази в коді виразу for.
  4. Перед входом у викликану функцію. Порядок обчислення аргументів не визначається, але ця точка перебігу значить, що всі їхні побічні ефекти завершуються до входу в функцію. У виразі 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 невизначений.
  5. Коли відбувається повернення з функції, після того як значення до повернення копіюється в викликальний контекст. (Ця точка перебігу визначена лиш стандарті С++; вона тільки неявно присутня в C.[4])
  6. По завершені ініціалізатора; наприклад, після завершення обчислення 5 в оголошенні int a = 5;.

Примітки

  1. Пункт 6.5#2 специфікації C99: "Між попередньою й наступною точкою перебігу значення збережене в об'єкті має змінитися через обчислення виразу не більше одного разу. Далі більше, доступ до попереднього значення може бути надано лише для визначення значення, що буде збережене."
  2. Додаток до специфікації C99 перелічує обставини за яких можуть бути присутні точкі перебігу.
  3. Стандарт С++ 1998 перелічує точки перебігу в розділі 1.9, параграфи 1618.
  4. Стандарт C++, ISO 14882:2003, розділ 1.9, долішня заувага 11.
This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.