Точка последовательности - Sequence point
А точка последовательности определяет любую точку в компьютерная программа с исполнение при котором гарантируется, что все побочные эффекты предыдущих оценок, и никаких побочных эффектов от последующих оценок еще не было. Они часто упоминаются со ссылкой на C и C ++, потому что они являются основной концепцией для определения достоверности и, если они допустимы, возможных результатов выражений. Иногда необходимо добавить дополнительные точки последовательности, чтобы сделать выражение определенным и гарантировать единый допустимый порядок оценки.
С C ++ 11, термин «точка последовательности» заменен на «последовательность». Есть три возможности:[1][2][3]
- Оценка выражения может быть последовательность до оценка другого выражения, или, что эквивалентно, оценка другого выражения последовательность после что из первого.
- Оценка выражений неопределенная последовательность, это означает, что один из них следует за другим, но не определен.
- Оценка выражений непоследовательный.
Выполнение непоследовательных оценок может перекрываться, что приводит к катастрофическим последствиям. неопределенное поведение если они поделятся государственный. Такая ситуация может возникнуть в параллельные вычисления, вызывая условия гонки. Однако это уже может возникнуть в простых несовпадающих ситуациях, таких как (а = 1) + (Ь = а)
, где часть задания а
(например, половина битов) может произойти до б = а
, а остальное - после этого, так что после вычисления выражения б
может содержать бессмысленное промежуточное состояние а
.
Примеры двусмысленности
Рассмотрим два функции f ()
и грамм()
. В C и C ++ +
оператор не связан с точкой последовательности, и поэтому в выражение f () + g ()
возможно, что либо f ()
или же грамм()
будет выполнено первым. Оператор запятая вводит точку последовательности, и поэтому в коде f (), g ()
порядок оценки определен: первый f ()
называется, а затем грамм()
называется.
Точки последовательности также вступают в игру, когда одна и та же переменная изменяется более одного раза в одном выражении. Часто цитируемым примером является C выражение я = я ++
, который, по-видимому, оба присваивает я
его предыдущее значение и увеличивается я
. Окончательное значение я
неоднозначен, потому что, в зависимости от порядка вычисления выражения, приращение может происходить до, после или чередоваться с присвоением. Определение конкретного языка может указывать одно из возможных поведений или просто говорить, что поведение неопределенный. В C и C ++ вычисление такого выражения приводит к неопределенному поведению.[4] Другие языки, например C # определить приоритет оператора присваивания и приращения таким образом, чтобы результат выражения я = я ++
гарантировано.
Точки последовательности в C и C ++
В C[5] и C ++,[6] точки последовательности встречаются в следующих местах. (В C ++ перегруженные операторы действуют как функции, и поэтому операторы, которые были перегружены, вводят точки последовательности так же, как вызовы функций.)
- Между вычислением левого и правого операндов && (логическое И ), || (логическое ИЛИ ) (как часть оценка короткого замыкания ), и операторы запятой. Например, в выражении
*п++ != 0 && *q++ != 0
, все побочные эффекты подвыражения*п++ != 0
завершаются до любой попытки доступаq
. - Между вычислением первого операнда троичного оператор "вопросительный знак" и второй или третий операнд. Например, в выражении
а = (*п++) ? (*п++) : 0
после первого*п++
, что означает, что он уже был увеличен к моменту выполнения второго экземпляра. - В конце полного выражения. В эту категорию входят операторы выражения (например, присваивание
а=б;
), операторы возврата, управляющие выраженияесли
,выключатель
,пока
, или жеделать
-пока
операторы, и все три выражения вза
утверждение. - До того, как функция будет введена в вызов функции. Порядок, в котором оцениваются аргументы, не указан, но эта точка последовательности означает, что все их побочные эффекты завершаются до того, как функция будет введена. В выражении
ж(я++) + грамм(j++) + час(k++)
,ж
вызывается с параметром исходного значенияя
, ноя
увеличивается перед входом в телож
. По аналогии,j
иk
обновляются перед вводомграмм
ичас
соответственно. Однако не уточняется, в каком порядкеж()
,грамм()
,час()
выполняются, ни в каком порядкея
,j
,k
увеличиваются. Если телож
обращается к переменнымj
иk
, он может обнаружить, что оба, ни один из них или только один из них были увеличены. (Вызов функцииж(а,б,c)
является нет использование оператора запятой; порядок оценкиа
,б
, иc
не указано.) - При возврате функции после того, как возвращаемое значение копируется в вызывающий контекст. (Эта точка последовательности указана только в стандарте C ++; она присутствует только неявно в C.[7])
- В конце инициализатор; например, после оценки
5
в декларацииint а = 5;
. - Между каждым декларатором в каждой последовательности деклараторов; например, между двумя оценками
а++
вint Икс = а++, у = а++
.[8] (Это нет пример оператора запятой.) - После каждого преобразования, связанного со спецификатором формата ввода / вывода. Например, в выражении
printf("фу% п% д", &а, 42)
, после% n
оценивается и перед печатью42
.
Рекомендации
- ^ «ISO / IEC 14882: 2011». Получено 2012-07-04.
- ^ «Более тонкая альтернатива точкам последовательности (пересмотренная) (WG21 / N2239 J16 / 07-0099)». Получено 2012-07-05.
- ^ «Порядок оценки». Получено 2015-10-14.
- ^ Пункт 6.5 № 2 C99 Технические характеристики: "Между предыдущей и следующей точкой последовательности объект должен иметь свое сохраненное значение, измененное не более одного раза при оценке выражения. Кроме того, к предыдущему значению необходимо обращаться только для определения значения, которое необходимо сохранить."
- ^ Приложение C к C99 В спецификации перечислены обстоятельства, при которых можно предположить точку последовательности.
- ^ Стандарт C ++ 1998 года перечисляет точки последовательности для этого языка в разделе 1.9, параграфах 16–18.
- ^ Стандарт C ++, ISO 14882: 2003, раздел 1.9, сноска 11.
- ^ Стандарт C ++, ISO 14882: 2003, раздел 8.3: "Каждый инициализатор-декларатор в объявлении анализируется отдельно, как если бы он был сам по себе в объявлении."
внешняя ссылка
- Вопрос 3.8 FAQ для comp.lang.c