Является ли этот четко определенный код?

Я все еще немного смущен, прочитав эту тему. Является ли следующее выражение С++ *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));

таким образом, ваше расстройство.