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

时间:2012-11-09 23:48:09

标签: c++ operators operator-precedence sequence-points

以下是测试代码:

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被侵犯。

4 个答案:

答案 0 :(得分:20)

评估的表达式与完成副作用之间存在差异。

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

答案 1 :(得分:8)

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

a = x + y;

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

事实上,在某些体系结构上,可以发出同时评估xy的代码 - 例如,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; (如果与关联性相比,优先级是主要的) 因此,通过上面的例子,我们可以说,与优先级

相比,关联性是主要的