Точка последовательности после оператора return?

В моем ответе на вопрос здесь Я объяснил, что происходит, когда постфикс ++ используется для глобальной переменной в той же строке, что и оператор return.

В информационном приложении C к C11 указано, что точка следования находится сразу после return, и содержится ссылка на нормативную главу 6.8.6.4, где нет текста, касающегося точек следования.

Где в стандарте C я могу найти нормативный текст, утверждающий, что после оператора return есть точка следования?

(Я нашел только нормативный текст, в котором говорится об этом для библиотечных функций, в качестве особого случая, в 7.1.4/3.)


person Lundin    schedule 26.03.2013    source источник


Ответы (2)


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
comment
Спасибо, текст в 6.8/4 был тем, что я искал. И, видимо, это было разъяснено в C11, потому что в C99 не было §4. Однако я не следую вашему примеру в отношении неопределенного поведения, поскольку есть также точка последовательности после того, как все параметры функции были оценены, но до вызова функции. Таким образом, каждая функция с оператором return защищена точками следования как в начале, так и в конце. Поэтому я считаю, что ваш пример - это просто неопределенное поведение, поскольку мы не можем знать, оценивается ли сначала Foo() или a. - person Lundin; 26.03.2013
comment
@Lundin: Хорошее замечание о точке последовательности между оценкой параметра и вызовом функции. Это означает, что есть разница между двумя правилами. Я обновил ответ. - person Eric Postpischil; 26.03.2013
comment
Существуют ли какие-либо случаи, когда отсутствие точки последовательности между оценкой возвращаемого значения и оценкой любой части включающего выражения, которая будет оцениваться как текст, позволяет компиляторам обрабатывать код с большей пользой, чем это было бы возможно в противном случае? Если нет, есть ли какая-то причина, по которой любой, кто хочет создавать или использовать качественные компиляторы, должен заботиться о том, обязательна ли там точка последовательности? - person supercat; 27.05.2021

Не думаю, что вы найдете то, что ищете. no text regarding sequence points can be found это правда, это подразумевается только разделом 6.8 п.4.

Стандарт C++ (ISO/IEC 14882:2003) в разделе 1.9 (сноска 11) констатирует тот факт, что точка следования после возврата не явно указывается где-либо в стандартах C:

11) Точка следования при возврате функции явно не указана в ISO C и может считаться избыточной с точками следования в полных выражениях, но в C++ важна дополнительная ясность. В C++ есть больше способов, которыми вызываемая функция может завершить свое выполнение, например, создание исключения.

person Mike    schedule 26.03.2013
comment
@larsmans да ... это было немного лишним, не так ли? Спасибо за исправление. - person Mike; 26.03.2013
comment
@Майк Спасибо. Кажется, это было исправлено в C11 согласно 6.8 §4. В C99 этого абзаца не было. - person Lundin; 26.03.2013