- Точка следования
-
Точка следования (англ. 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++ определены следующие точки следования:
- Между вычислением левого и правого операндов в операторах && (логическом И), || (логическом ИЛИ) и операторах-запятых. Например, в выражении
*p++ != 0 && *q++ != 0
все побочные эффекты левого операнда*p++ != 0
проявятся до начала каких либо действий в правом. - Между вычислением первого и второго или третьего операндов в операторе условия. В строке
a = (*p++) ? (*p++) : 0
точка находится после первого операнда*p++
, при выполнении второгоp
уже увеличена на 1. - В конце всего выражения. Эта категория включает в себя инструкции-выражения (
a=b;
), выражения в инструкциях return, управляющие выражения в круглых скобках инструкций ветвленияif
илиswitch
и цикловwhile
илиdo
-while
и все три выражения в круглых скобках циклаfor
. - Перед входом в вызываемую функцию. Порядок, в котором вычисляются аргументы не определен, но эта точка следования гарантирует, что все ее побочные эффекты проявятся на момент входа в функцию. В выражении
f(i++) + g(j++) + h(k++)
каждая из трёх переменных:i
,j
иk
, принимает новое значение перед входом вf
,g
иh
соответственно. Однако, порядок вызова функцийf()
,g()
,h()
неопределён, следовательно неопределён и порядок инкрементаi
,j
,k
. Значенияj
иk
в теле функцииf
оказываются неопределенными. Следует заметить, вызов функции нескольких аргументовf(a,b,c)
не является случаем применения оператора-запятой и не определяет порядок вычисления значений аргументов. - При возврате из функции, на момент когда возвращаемое значение будет скопировано в вызывающий контекст.(Явно описана только в стандарте С++, в отличие от С.)
- В объявлении с инициализацией на момент завершения вычисления инициализирующего значения, например, на момент завершения вычисления
(1+i++)
вint a = (1+i++);
.
(В C++ перегруженные операторы выступают в роли функций, поэтому точкой следования является вызов перегруженного оператора)
См. также
- Приоритет операций
Ссылки
Категория:- Программирование
- Между вычислением левого и правого операндов в операторах && (логическом И), || (логическом ИЛИ) и операторах-запятых. Например, в выражении
Wikimedia Foundation. 2010.