Является ли этот четко определенный код?
Я все еще немного смущен, прочитав эту тему. Является ли следующее выражение С++ *d++ = ~(*d);
корректным? Да, я знаю, что сложные выражения вроде этого уродливые. Я не писал это.
Я вижу небольшую разницу в сгенерированной сборке, когда сравниваю ее с:
*d = ~(*d);
d++;
Сборка:
*d++ = ~(*d);
0x83384 LDR R3,[R0 <d>,4] <<diff
0x83388 ADD R1 <c>, R1 <c>, 1
0x8338c MVN R3, R3
0x83390 STR R3,[R0 <d>],4
против
*d = ~(*d);
d++;
0x83384 LDR R3,[R0 <d>]
0x83388 ADD R1 <c>, R1 <c>, 1
0x8338c MVN R3, R3
0x83390 STR R3,[R0 <d>],4
Спасибо!
Ответы
Ответ 1
*d++ = ~(*d);
В этом выражении ни один объект не имеет нового значения, хранящегося в нем более одного раза. Значение d + 1
сохраняется в d
как побочный эффект оператора инкремента (d++
) и значение объекта, на которое указывает d
, до того, как это приращение будет записано оператором присваивания.
Проблема заключается в том, что читается d
, а не просто для определения возвращаемого значения (т.е. d + 1
), но также считывается для определения адреса для чтения из подвыражения правой стороны ~(*d)
.
Это нарушает третье предложение ISO/IEC 14882: 2003 5 [expr]/4 (первое предложение опущено для краткости):
[...] Между предыдущей и следующей точками последовательности скалярный объект должен иметь значение хранимого значения, измененное не более одного раза путем оценки выражения. Кроме того, доступ к предыдущему значению должен получить только для определения значения, которое необходимо сохранить. Требования этого параграфа должны соблюдаться для каждого допустимого упорядочения подвыражений полного выражения; в противном случае поведение undefined.
Ответ 2
Ваше выражение имеет undefined (в отличие от неуказанного) поведения. Ассемблерный код также может играть в Бетховен 9-го и соответствовать стандарту.
Из Священного стандарта, глава 5, стих 4:
Между предыдущей и следующей точками последовательности скалярный объект должен иметь значение, которое его хранимое значение изменялось не более одного раза путем оценки выражения.
Следовательно, код плохо сформирован. Я не знаю, нужен ли стандартный компилятор, чтобы выполнить диагностику, но я был достаточно укушен в этом, что я готов поспорить, что это не так.
Обратитесь к @Prasoon Saurav за отличной экспозицией там для более подробной информации.
Ответ 3
Вы просто не знаете, когда оценивается ++. Я полагаю, ваш компилятор оценивает его до ~(*d)
, что приводит к
*d = ~(*(d+1));
таким образом, ваше расстройство.