Каков результат + = в C и С++?
У меня есть следующий код:
#include <stdio.h>
int main(int argc, char **argv) {
int i = 0;
(i+=10)+=10;
printf("i = %d\n", i);
return 0;
}
Если я попытаюсь скомпилировать его как источник C с помощью gcc, я получаю сообщение об ошибке:
error: lvalue required as left operand of assignment
Но если я скомпилирую его как источник С++ с помощью g++, я не получаю ошибки и при запуске исполняемого файла:
i = 20
Почему различное поведение?
Ответы
Ответ 1
Семантика сложных операторов присваивания различна в C и С++:
Стандарт C99, 6.5.16, часть 3:
Оператор присваивания сохраняет значение в объекте, обозначенном левым операндом. выражение присваивания имеет значение левого операнда после назначения, но не является именующий.
В С++ 5.17.1:
Оператор присваивания (=) и составные операторы присваивания все группы справа налево. Все требуют модификации lvalue в качестве своего левого операнда и вернуть значение lvalue с типом и значением левого операнда после выполнения задания.
EDIT: Поведение (i+=10)+=10
в С++ - это undefined в С++ 98, но хорошо определенное в С++ 11. См. этот ответ на вопрос NPE для соответствующих частей стандартов.
Ответ 2
Помимо недействительного кода C, строка
(i+=10)+=10;
приведет к поведению undefined как в C, так и в С++ 03, потому что он дважды изменит i
между точками последовательности.
Что касается того, почему это разрешено компилировать в С++:
[С++ N3242 5.17.1] Оператор присваивания (=) и составные операторы присваивания все группы справа налево. Все требуют модифицируемое значение lvalue как его левый операнд и возвращает lvalue, ссылаясь на левый операнд.
В этом же пункте говорится, что
Во всех случаях назначение упорядочивается после значения вычисление правого и левого операндов и перед вычислением значения выражения присваивания.
Это говорит о том, что в С++ 11 выражение больше не имеет поведения undefined.