Является ли `C == C++` неопределенным поведением?

Друг говорит мне, что после:

int C = anything;

C == C++ будет иметь значение true, Это задумано как шутка, своего рода опровержение часто заявляемого "C не то же самое, что C++".

Тем не менее, так как == это не точка последовательности, я утверждаю, что это на самом деле неопределенное поведение. Программа может сначала оценить C++, чтобы C > C++ а также C == C++ оба не определены. Тем не мение, C >= C++ всегда будет оцениваться как правда. То же самое, конечно, верно, когда операнды перевернуты (C++ <= C всегда верно, а все остальное не определено).

Является ли этот анализ правильным?

2 ответа

Решение

Все случаи приводят к неопределенному поведению и непредсказуемым результатам.

Проект стандарта C++11 говорит нам, что, если не указано иное, порядок вычислений операндов не секвенирован, и если один и тот же скалярный объект изменяется более одного раза из-за побочных эффектов, не связанных с последовательностью, чем у нас неопределенное поведение. Это также не определено, если нам нужно изменить объект и вычислить значение объекта для другого операнда. Это описано в проекте стандарта C++11 1.9

За исключением отмеченных случаев, оценки операндов отдельных операторов и подвыражений отдельных выражений не являются последовательными. [Примечание: В выражении, которое оценивается более одного раза во время выполнения программы, непоследовательные и неопределенно последовательные оценки ее подвыражений не должны выполняться последовательно в различных оценках. - примечание конца] Вычисления значений операндов оператора секвенируются до вычисления значения результата оператора. Если побочный эффект на скалярный объект не секвенирован относительно другого побочного эффекта на тот же скалярный объект или вычисления значения с использованием значения того же скалярного объекта, поведение не определено.

Ни операторы равенства, ни операторы отношений в сечениях 5.9 Реляционные операторы и 5.10 Операторы равенства определяют последовательность операндов.

clang также выдает предупреждение для этого случая, похоже, что по умолчанию оно должно выглядеть примерно так ( смотрите вживую):

 warning: unsequenced modification and access to 'C' [-Wunsequenced]
  if( C == C++ )
      ~     ^

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

Если не указано иное, порядок вычисления операндов отдельных операторов и подвыражений отдельных выражений, а также порядок, в котором возникают побочные эффекты, не определены.57) Между предыдущей и следующей точкой последовательности скалярному объекту необходимо изменить свое сохраненное значение не более одного раза путем оценки выражения. Кроме того, предварительное значение должно быть доступно только для определения значения, которое будет сохранено. Требования этого параграфа должны выполняться для каждого допустимого упорядочения подвыражений полного выражения; в противном случае поведение не определено.

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

Ты прав. Даже компилятор говорит так: компиляция

#include <iostream>

int main()
{
  int C = 0;
  if (C == C++) {
  ...

результаты в:

main.cpp: In function 'int main()':
main.cpp:6:17: warning: operation on 'C' may be undefined [-Wsequence-point]
     if (C == C++) {
                 ^

( Колиру)

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