以下是测试代码:
int main()
{
int a = 3;
int b = 4;
a = a + b - (b = a);
cout << "a :" << a << " " << "b :" << b << "\n";
return 0;
}
编译它会发出以下警告:
> $ g++ -Wall -o test test.cpp test.cpp: In function ‘int main()’:
> test.cpp:11:21: warning: operation on ‘b’ may be undefined
> [-Wsequence-point]
为什么操作不确定?
根据我的理解,首先应该评估子表达式(b = a)
,因为()的优先级更高,因此设置b = a。然后,由于'+'和' - '具有相同的优先级,因此表达式将以左关联方式进行计算。因此,接下来应评估a + b
,最后应从(b = a)
中减去a + b
的结果。我在这里看不到任何sequence-point rule被侵犯。
答案 0 :(得分:20)
评估的表达式与完成副作用之间存在差异。
由于括号的优先级较高,因此将在减法之前评估b = a
赋值表达式。作为评估结果,它将提供a
的值。然而,将该值写入b
可能直到下一个序列点才完成,在这种情况下,该序列点是完整表达式的结束。因此,整体表达式的最终结果是未定义的,因为减法可能在赋值之前或之后取b
的值。
答案 1 :(得分:8)
在C ++中,算术表达式中的子表达式没有时序。
a = x + y;
首先评估x
,还是y
?编译器可以选择其中之一,也可以选择完全不同的东西。评估顺序不与运算符优先级相同:严格定义运算符优先级,评估顺序仅定义为程序具有序列点的粒度。
事实上,在某些体系结构上,可以发出同时评估x
和y
的代码 - 例如,VLIW体系结构。
答案 2 :(得分:-1)
要解决它,请将它们分成两个不同的语句。
PS:不要忘记人类在进行算术运算时可能会犯错误。因此,最好通过在不同的语句中分离它们来使操作更清晰。我希望我能帮忙。int main()
{
int a = 3;
int b = 4;
/* Two different Statements*/
b = a;
/* or a = a + b - a */
a = a + b - b;
cout<<"a :"<<a<<" "<<"b :"<<b<<"\n";
return 0;
}
答案 3 :(得分:-1)
a = b + a - a;
只是写成
a = b + a - (b = a)
------&GT;&GT; (exp 1)
以下三个结果与(exp 1)相同
a = (b + a - (b = a));
a = ((b + a) - (b = a));
a = (b + a) - (b = a);
观测 +, - 运算符具有相同的优先级,也具有从左到右的关联性 因此,首先执行“b + a”,然后在减法之前将“a”值分配给“b”
现在观察以下内容 当a = 10且b = 20时;
a = (b = a) - b + a;
=======&gt; a = 10; b = 10
a = ((b = a) - b + a);
=======&gt; a = 10; b = 10
a = ((b = a) - (b + a));
=======&gt; a = -10; b = 10
从上面的表达式中可以清楚地看出,即使首先执行最里面的括号,首先遵循关联性,然后是优先级
注意:
避免外括号和内括号的优先级之间的混淆
请考虑以下表达式
a = (b + a - (b = a))
=====&gt;实际结果=&gt; a = 20,b = 10;
本来是a = 10,b = 10; (如果与关联性相比,优先级是主要的)
因此,通过上面的例子,我们可以说,与优先级