Каков результат += в C и 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
Но если я скомпилирую его как исходный код C++, используя g++, я не получаю ошибки, и когда я запускаю исполняемый файл:
i = 20
Почему разное поведение?
2 ответа
Семантика составных операторов присваивания различна в C и C++:
Стандарт С99, 6.5.16, часть 3:
Оператор присваивания сохраняет значение в объекте, обозначенном левым операндом. Выражение присваивания имеет значение левого операнда после присваивания, но не является lvalue.
В C++ 5.17.1:
Оператор присваивания (=) и составные операторы присваивания все группы справа налево. Все они требуют изменяемого lvalue в качестве своего левого операнда и возвращают lvalue с типом и значением левого операнда после того, как присвоение выполнено.
РЕДАКТИРОВАТЬ: поведение (i+=10)+=10
в C++ не определен в C++98, но хорошо определен в C++11. Смотрите этот ответ на вопрос NPE для соответствующих частей стандартов.
В дополнение к недействительному коду C, строка
(i+=10)+=10;
приведет к неопределенному поведению как в C, так и в C++03, потому что это изменит i
дважды между точками последовательности.
Что касается того, почему разрешено компилировать в C++:
[C++ N3242 5.17.1] Оператор присваивания (=) и составные операторы присваивания все группы справа налево. Все они требуют изменяемого lvalue в качестве своего левого операнда и возвращают lvalue, ссылаясь на левый операнд.
В том же пункте говорится, что
Во всех случаях присваивание выполняется после вычисления значения правого и левого операндов и перед вычислением значения выражения присваивания.
Это говорит о том, что в C++11 выражение больше не имеет неопределенного поведения.