Точка следования

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Точка следования (англ. Sequence point) — в программировании любая точка программы, в которой гарантируется, что все побочные эффекты предыдущих вычислений уже проявились, а побочные эффекты последующих еще отсутствуют.

Их часто упоминают, говоря о языках C и C++, поскольку в этих языках особенно просто записать выражение, значение которого может зависеть от неопределённого порядка проявления побочных эффектов. Добавление одной или нескольких точек следования задает порядок более жестко и является одним из методов достижения устойчивого (то есть корректного) результата.

Примеры неоднозначности[править | править вики-текст]

Рассмотрим две функции f() и g(). По стандарту языка C и C++ оператор сложения <+> не является точкой следования, поэтому в выражении g()+f() возможно, что любая из функций может быть вычислена первой. Оператор <,> является точкой следования, и потому для выражения f(),g() функции будут вычислены в том порядке, в котором записаны: сначала f(), затем g(). Тип и значение всего выражения определяются в данном случае функцией g(), значение же f() будет утеряно.

Точки следования необходимы в ситуации, когда одна и та же переменная изменяется в выражении более одного раза. Часто в качестве примера приводят выражение i=i++, в котором происходит присваивание переменной i и её же инкремент. Какое значение примет i? Стандарт языка должен либо указать одно из возможных поведений программы как единственно допустимое, либо указать диапазон допустимых поведений (см. неуточняемое поведение), либо указать, что поведение программы в данном случае совершенно не определено (см. неопределённое поведение). В языках C и C++ вычисление выражения i=i++ приводит к неопределённому поведению, поскольку это выражение не содержит внутри себя ни одной точки следования.

Точки следования в языках C и C++[править | править вики-текст]

В C и C++ определены следующие точки следования:

  1. Между вычислением левого и правого операндов в операторах && (логическом И), || (логическом ИЛИ) и операторах-запятых. Например, в выражении *p++ != 0 && *q++ != 0 все побочные эффекты левого операнда *p++ != 0 проявятся до начала каких либо действий в правом.
  2. Между вычислением первого и второго или третьего операндов в операторе условия. В строке a = (*p++) ? (*p++) : 0 точка находится после первого операнда *p++, при выполнении второго p уже увеличена на 1.
  3. В конце всего выражения. Эта категория включает в себя инструкции-выражения (a=b;), выражения в инструкциях return, управляющие выражения в круглых скобках инструкций ветвления 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) не является случаем применения оператора-запятой и не определяет порядок вычисления значений аргументов.
  5. При возврате из функции, на момент когда возвращаемое значение будет скопировано в вызывающий контекст.(Явно описана только в стандарте С++, в отличие от С.)
  6. В объявлении с инициализацией на момент завершения вычисления инициализирующего значения, например, на момент завершения вычисления (1+i++) в int a = (1+i++);.

(В C++ перегруженные операторы выступают в роли функций, поэтому точкой следования является вызов перегруженного оператора)

См. также[править | править вики-текст]

Ссылки[править | править вики-текст]