Множественные операции преинкремента над переменной в C ++ (C?) - PullRequest
17 голосов
/ 11 сентября 2010

Почему следующий код компилируется в C ++?

int phew = 53;
++++++++++phew ;

Тот же код не работает в C, почему?

Ответы [ 2 ]

29 голосов
/ 11 сентября 2010

Примечание. Два отчета о дефектах DR # 637 и DR # 222 важны для понимания приведенного ниже объяснения поведения.


Для пояснения вC ++ 0x есть value computations и side effects.Побочным эффектом, например, является присвоение, а вычисление значения определяет, к чему относится lvalue или считывает значение из lvalue.Обратите внимание, что в C ++ 0x больше нет точек последовательности, и этот материал сформулирован в терминах «секвенировано до» / «секвенировано после».И утверждается, что

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

++v эквивалентно v += 1, что эквивалентно v = v + 1 (за исключением того, что v оценивается только один раз).Это дает ++ (v = v + 1), который я напишу как inc = inc + 1, где inc относится к результату lvalue v = v + 1.

В C ++ 0x ++ ++v не является неопределенным поведением, потому что для a = b присваивание выполняется последовательно после вычисления значения b и a, но до вычисления значения выражения присваивания.Отсюда следует, что присвоение в v = v + 1 упорядочено до вычисления значения inc.И присвоение в inc = inc + 1 упорядочивается после вычисления значения inc.В итоге оба назначения будут упорядочены, и не будет неопределенного поведения.

14 голосов
/ 11 сентября 2010

Это связано с тем, что в C++ оператор предварительного приращения возвращает lvalue и требует, чтобы его операнд был lvalue.

++++++++++phew ; интерпретируется как ++(++(++(++(++phew))))

Однако ваш код вызывает Undefined Behaviour, потому что вы пытаетесь изменить значение phew более одного раза между двумя точками последовательности .

В C оператор предварительного увеличения возвращает и rvalue и требует, чтобы его операнд был lvalue. Таким образом, ваш код не компилируется в режиме C.

...