Является ли (a = 1) = 2 неопределенным поведением в С++ 98?

Аналогичные коды, например (a+=1)%=7;, где a — переменная int.

Мы знаем, что оператор += или = не является точкой последовательности, поэтому у нас есть два побочных эффекта между двумя соседними точками последовательности. (здесь мы используем правила точки следования cpp98)

Однако операторы присваивания, такие как += или =, гарантируют возврат lvalue после присваивания, что означает, что порядок выполнения в некоторой степени "определен".

Так это неопределенное поведение?


person inverse    schedule 01.04.2020    source источник
comment
Я думаю, что круглые скобки предотвращают неопределенное поведение вашего титульного выражения. Однако, если вы должны были иметь: int a = 2; (a = 1) = a;, то это является неопределенным (как это имеет clang-cl: модификация без последовательности и доступ к 'a').   -  person Adrian Mole    schedule 01.04.2020
comment
Короткий ответ: да, поведение не определено. В C++98 круглые скобки не указывают точку последовательности, а двойное изменение переменной между двумя точками последовательности, т. е. операторы += и %= изменяют a, приводит к неопределенному поведению.   -  person Peter    schedule 01.04.2020


Ответы (1)


(a=1)=2 был неопределенным до C++11, поскольку оператор = не вводил точку следования, и поэтому a модифицируется дважды без промежуточной точки следования. То же самое относится к (a+=1)%=7

Текст был:

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

Стоит отметить, что описание оператора присваивания некорректно:

Результатом операции присваивания является значение, сохраненное в левом операнде после выполнения присваивания; результатом является lvalue.

Если результатом является lvalue, то результатом не может быть сохраненное значение (это будет rvalue). Lvalues ​​обозначают ячейки памяти. Кажется, что это предложение подразумевает отношение упорядочивания, но независимо от того, как мы хотим его интерпретировать, в нем не используется термин «точка последовательности», и поэтому применяется более ранний текст о точках последовательности.

Во всяком случае, эта формулировка ставит под сомнение такие выражения, как (a=1) + 2. Версия секвенирования C++11 устранила все эти неясности.

person M.M    schedule 01.04.2020
comment
Когда стандарты были впервые написаны, никто не думал, что кого-то будет волновать, действительно ли Стандарт определяет крайний случай, который компиляторы последовательно обрабатывают одинаково и где не было никакой предполагаемой выгоды от выполнения чего-либо еще, если только не возникла ситуация, когда выполнение чего-то другого могло бы предложить значительная и непредвиденная выгода. В этом случае наличие определенного поведения исключит возможность реализации рассматриваемой выгоды, а оставление его неопределенным позволит исполнителю взвесить затраты и выгоды обычного поведения по сравнению с альтернативным. - person supercat; 02.04.2020
comment
@supercat компиляторы постоянно обрабатывали (a=1)=2 ? - person M.M; 03.04.2020
comment
Делали ли какие-либо компиляторы, которые обрабатывали (a=1) как неконстантное lvalue, что-либо, кроме сохранения 1 перед обработкой второго присваивания? - person supercat; 03.04.2020
comment
@supercat, я вас спрашиваю, вы тот, кто утверждает, что компиляторы последовательно обрабатывают их одинаково - person M.M; 03.04.2020