Введение
В стандарте C11 (ISO/IEC 9899: 2011) введено новое определение последовательности побочных эффектов в выражении (см. соответствующий вопрос). Концепция точки последовательности была дополнена секвенированными ранее и упорядочена после отношений, которые теперь являются основой для всех определений.
Раздел 6.5 "Выражения", пункт 2 гласит:
Если побочный эффект скалярного объекта не зависит от другого побочного эффекта на том же скалярном объекте или вычислении значения, используя значение одного и того же скаляра объект, поведение undefined. Если имеется несколько допустимых порядков подвыражения выражения, поведение undefined, если такая непоследовательная сторона эффект происходит в любом из упорядочений.
В дальнейшем в разделе 6.5.16 "Операторы присваивания" точка 3 указывает:
Побочный эффект обновления сохраненного значения левого операнда секвенируется после вычисления значений левого и правого операндов. Оценки операнды не подвержены влиянию.
Проблема
Первый цитируемый параграф (6.5/2) поддерживается двумя примерами (такими же, как в стандарте C99):
Первый пример
a[i++] = i; //! undefined
a[i] = i; // allowed
Это можно легко объяснить с помощью определений:
- Если побочный эффект скалярного объекта не влияет на (...) вычисление значения с использованием значения одного и того же скалярного объекта, поведение undefined. (6,5/2),
- Оценки операндов не имеют никакого значения. [в пределах задания] (6.5.16/3).
Таким образом, побочный эффект i++
(LHS) не зависит от i
(RHS), что дает поведение undefined.
Второй пример
i = ++i + 1; //! undefined
i = i + 1; // allowed
Этот код, однако, приводит к определенному поведению в обоих случаях:
- побочный эффект обновления сохраненного значения левого операнда упорядочивается после вычисления значений левого и правого операндов.
Итак, выполнение ++i + 1
должен предшествовать побочному эффекту обновления i
, что означает, что побочный эффект не сказывается на скалярном объекте, не подверженном влиянию либо на другой побочный эффект на один и тот же скалярный объект, либо на вычисление значения с использованием значения одного и того же скалярного объекта.
Вопрос
Эти примеры легко объяснить с помощью терминов и определений, представленных стандартом C99 (см. соответствующий вопрос). Но почему i = ++i + 1
undefined в соответствии с терминологией C11?