C 2011 (черновик n1570) 6.8 4: «Каждое из следующего является полным выражением: … (необязательное) выражение в операторе return. Существует точка последовательности между оценкой полного выражения и оценкой следующего полного выражения, которое нужно оценить».
Таким образом, технически точка последовательности находится не после return, а между оценкой выражения в return и следующим выражением. Рассмотрим этот код, вызываемый, когда a
изначально равен 0:
int a = 0;
int Foo(void) { return a++; }
void Bar(void)
{
int b = Foo() + a;
…
}
В Foo() + a
не указано, будет ли сначала оцениваться Foo()
или a
. Мы рассмотрим оба порядка в свете обоих возможных правил (точка последовательности после return по сравнению с точкой последовательности между выражением return и следующим полным выражением). Если реализация сначала делает a
, то она должна сделать:
a
Sequence point
Foo()
+
а затем следует какое-то другое полное выражение, так что по любому правилу будет точка следования, и этот код одинаков в любом случае, насколько нам известно. В результате b
устанавливается равным 0.
Если реализация сначала выполняет Foo()
, то с правилом «точка последовательности после возврата» реализация должна выполнить:
Sequence point
Foo()
Sequence point
a
+
Этот код определял бы поведение: a
увеличивается побочным эффектом в Foo
, и это завершается до обращения к a
, затем выполняется +
. В результате a
устанавливается равным 1. Хотя результат может быть 0 или 1 с этим правилом «точка последовательности после return», просто не указано, какой из двух порядков используется; поведение не является полностью неопределенным.
Однако, если реализация сначала делает Foo()
и использует стандартное правило C "точка последовательности между выражением return и следующим полным выражением", то мы имеем:
Sequence point
Foo()
???
a
???
+
???
«???» отмечайте места, где может находиться требуемая точка следования — в любом месте после return и перед следующим полным выражением. В этом случае значение a
может быть доступно в a
и изменено в Foo()
, а промежуточная точка последовательности отсутствует. Это неопределенное поведение.
Следовательно, правило «точка последовательности после выражения return и перед следующим полным выражением» отличается от «точки последовательности сразу после return»; в этом примере у первого есть неопределенное поведение, а у второго нет.
person
Eric Postpischil
schedule
26.03.2013