Будет ли я =i++ заново определен в C17?

После того, как я наткнулся на вопрос " Почему эти конструкции используют неопределенное поведение до и после приращения?", Сегодня я решил взять новейший черновик для следующего стандарта C, который я смог найти, и прочитать о нем больше.
Вскоре после того, как я обнаружил следующий абзац в черновике C17:

Выражение - это последовательность операторов и операндов, которая задает вычисление значения, или которая обозначает объект или функцию, или которая генерирует побочные эффекты, или которая выполняет их комбинацию. Вычисления значений операндов оператора секвенируются до вычисления значения результата оператора
Источник: ISO / IEC 9899: 2017, раздел 6.5.1 "Выражения"

Теперь я немного растерялся. Разве это не значит, что i = i++ определяется поведение? Я посмотрел на другой проект, C99 на этот раз:

Выражение - это последовательность операторов и операндов, которая задает вычисление значения, или которая обозначает объект или функцию, или которая генерирует побочные эффекты, или которая выполняет их комбинацию.
Источник: ISO / IEC 9899: 1999, раздел 6.5.1 "Выражения".

Этого самого предложения не хватает!

Вопросы

  1. Я что-то не так понял?
  2. Ответы устарели?
  3. Я посмотрел на неправильный проект?

2 ответа

Решение

Выделенный вами отрывок говорит только о том, что выражения i++ а также i оцениваются до оценки полного выражения i = i++, Это все еще неопределенное поведение, потому что i изменяется более одного раза в выражении без точки последовательности.

Этот отрывок впервые появился в C11, поэтому нет изменений по сравнению с версией C17.

Полная история. В C99 у нас был этот текст для 6.5.16 оператора присваивания:

Побочный эффект обновления сохраненного значения левого операнда должен иметь место между предыдущей и следующей точкой последовательности.

Порядок оценки операндов не указан. Если предпринята попытка изменить результат оператора присваивания или получить к нему доступ после следующей точки последовательности, поведение не определено.

Это было изменено в C11 на:

Побочный эффект обновления сохраненного значения левого операнда упорядочен после вычислений значения левого и правого операнда. Оценки операндов не являются последовательными.

Это просто другая (и хуже) формулировка, две версии ведут себя одинаково - ключ является последним предложением в части C11, которая все еще выполняет это неопределенное поведение, так как вычисление левого операнда все еще не секвенировано по отношению к правому операнду. Вычисление значения относится только к отдельным операндам.

C17 имеет такой же текст, как C11. Итак, ответ: нет, i = i++; все еще неопределенное поведение в C17.


Просто для сравнения, сравните это с C++11 (5.17):

Во всех случаях присваивание выполняется после вычисления значения правого и левого операндов и перед вычислением значения выражения присваивания.

Это примерно тот же текст, что и в C11, без явного "вычисления операндов не секвенированы". Это было недостатком в C++11, не ясно, сделало ли это определенные выражения четкими или нет.

C++17 дает пояснение (8.5.18):

Во всех случаях присваивание выполняется после вычисления значения правого и левого операндов и перед вычислением значения выражения присваивания. Правый операнд упорядочен перед левым операндом.

Так в C++17 i=i++; определенно четко определены. И, как мы видим, формулировка является явной, в отличие от "непоследовательности" в C11/C17.

Другие вопросы по тегам