为什么表达式 a = a + b - ( b = a ) 在 c++ 中给出序列点警告?

Why does the expression a = a + b - ( b = a ) give a sequence point warning in c++?

本文关键字:警告 表达式 为什么 c++      更新时间:2023-10-16

以下是测试代码:

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,最后从a + b中减去(b = a)的结果。我在这里看不到任何违反的序列点规则。

正在计算的表达式和完成其副作用之间存在差异。

由于括号的优先级较高,b = a赋值表达式将在减法之前计算。它将提供作为评估结果的a值。但是,将该值写入b可能要到下一个序列点才能完成,在这种情况下,这是完整表达式的结尾。因此,整体表达式的最终结果是不确定的,因为减法可能会在赋值之前或之后取b的值。

在C++中,算术表达式中的子表达式没有时间顺序。

a = x + y;

x是先评估还是y? 编译器可以选择其中之一,也可以选择完全不同的内容。 计算顺序与运算符优先级不同:运算符优先级是严格定义的,并且评估顺序仅定义为程序具有序列点的粒度。

事实上,在某些体系结构上,可以发出同时评估xy的代码 - 例如,VLIW 体系结构。

为了解决这个问题,将它们分成两个不同的语句。

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;
}

a = b + a - a;只是写成

a = b + a - (b = a)------>> (经验 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;========> a = 10; b = 10a = ((b = a) - b + a);========> a = 10;b = 10

a = ((b = a) - (b + a));========> a = -10; b = 10 从上面的表达式中可以清楚地看出,即使最里面的括号首先被执行,也首先遵循结合性,然后是优先级。

注意: 避免混淆外括号和内括号的优先级 考虑以下表达式a = (b + a - (b = a))=====> 实际结果 => a = 20, b = 10; 本来是 a = 10,b = 10;(如果与结合性相比,优先级是主要的) 因此,通过上面的例子,我们可以说,与优先级相比,结合性是主要的。