c++ - пример - unspecified behavior




В C и C++ является ли выражение, использующее оператор запятой, например «a=b,++ a;» неопределенным? (2)

Возьмите эти три фрагмента кода C:

1) a = b + a++
2) a = b + a; a++
3) a = b + a, a++

Все знают, что пример 1 - очень плохая вещь, и явно вызывает неопределенное поведение. Пример 2 не имеет проблем. У меня вопрос по поводу примера 3. В этом выражении оператор запятой работает как точка с запятой? 2 и 3 эквивалентны или 3 так же неопределенны, как 1?

В частности, я рассматривал это в отношении чего-то вроде free(foo), foo = bar . Это в основном та же проблема, что и выше. Могу ли я быть уверен, что foo освобождается до его переназначения, или это явная проблема точки последовательности?

Я знаю, что оба примера в значительной степени бессмысленны, и имеет гораздо больше смысла просто использовать точку с запятой и покончить с этим. Я просто спрашиваю из любопытства.


Случай 3 хорошо определен.

Раздел 6.5.17 стандарта C, касающийся оператора запятой , гласит следующее:

2 Левый операнд оператора запятой оценивается как пустое выражение; существует последовательность между его оценкой и оценкой правого операнда. Затем вычисляется правый операнд; результат имеет свой тип и значение

Раздел 5.14 p1 стандарта C ++ 11 имеет похожий язык:

Пара выражений, разделенных запятой, оценивается слева направо; левое выражение является выражением отброшенного значения. Каждое вычисление значения и побочный эффект, связанный с левым выражением, упорядочивается перед каждым вычислением значения и побочным эффектом, связанным с правым выражением. Тип и значение результата - это тип и значение правого операнда; результат имеет ту же категорию значений, что и его правый операнд, и является битовым полем, если его правый операнд является glvalue и битовым полем.

Из-за точки последовательности a = b + a гарантированно будет полностью вычислено перед a++ в выражении a = b + a, a++ .

Что касается free(foo), foo = bar , это также гарантирует, что foo освобождается перед назначением нового значения.


a = b + a, a++; четко определен, но a = (b + a, a++); может быть неопределенным

Прежде всего, приоритет оператора делает выражение эквивалентным (a = (b+a)), a++; , где + имеет наивысший приоритет, затем следует = , а затем,. Оператор запятой включает точку последовательности между вычислением его левого и правого операнда. Таким образом, код, неинтересно, полностью эквивалентен:

a = b + a;
a++;

Что, конечно, четко определено.

Если бы мы вместо этого написали a = (b + a, a++); , то точка последовательности в операторе запятой не спасет день. Потому что тогда выражение было бы эквивалентно

(void)(b + a);
a = a++;
  • В C и C ++ 14 или старше, a = a++ не секвенируется (см. C11 6.5.16 / 3). Это означает, что это неопределенное поведение (согласно C11 6.5 / 2). Обратите внимание, что C ++ 11 и C ++ 14 были плохо сформулированы и неоднозначны.
  • В C ++ 17 или более поздних версиях операнды оператора = упорядочены справа налево, и это все еще четко определено.

Все это при условии, что перегрузка оператора C ++ не происходит. В этом случае параметры перегруженной операторной функции будут оценены, точка последовательности имеет место перед вызовом функции, и то, что происходит от этого, зависит от внутренних функций этой функции.





undefined-behavior