我有以下代码:
#include <stdio.h>
int main(int argc, char **argv) {
int i = 0;
(i+=10)+=10;
printf("i = %d\n", i);
return 0;
}
如果我尝试使用gcc将其编译为C源,我会收到错误:
error: lvalue required as left operand of assignment
但是如果我使用g ++将其编译为C ++源代码,我就不会出现错误,当我运行可执行文件时:
i = 20
为什么不同的行为?
答案 0 :(得分:132)
复合赋值运算符的语义在C和C ++中是不同的:
C99标准,6.5.16,第3部分:
赋值运算符将值存储在左操作数指定的对象中。一个 赋值表达式具有赋值后左操作数的值,但不是 左值。
在C ++ 5.17.1中:
赋值运算符(=)和复合赋值运算符从右到左分组。所有都需要修改 左值作为左操作数,并在赋值发生后返回左值操作数的类型和值的左值。
编辑: C ++中(i+=10)+=10
的行为在C ++ 98中未定义,但在C ++ 11中定义良好。有关标准的相关部分,请this answer查看问题的NPE。
答案 1 :(得分:51)
除了无效的C代码外,该行
(i+=10)+=10;
会导致C和C ++ 03中的未定义行为,因为它会在序列点之间修改i
两次。
至于为什么允许在C ++中编译:
[C ++ N3242 5.17.1]赋值运算符(=)和复合赋值运算符从右到左分组。都需要一个 可修改左值作为左操作数并返回左值操作数的左值。
同一段继续说
在所有情况下,分配都在值之后排序 计算右和左操作数,并在赋值表达式的值计算之前。
这表明在C ++ 11中,表达式不再具有未定义的行为。