序列点和运算符优先级之间的差异? 0_o

时间:2011-09-21 21:11:48

标签: c++

让我举一个例子:

a = ++a;

据说上述陈述有不明确的行为(我已经在SO上读过关于UB的文章)

但是根据优先级规则运算符前缀++的优先级高于赋值运算符=

所以a应首先递增,然后再分配给a。所以每个评估都是已知的,为什么它是UB?

5 个答案:

答案 0 :(得分:9)

这里要理解的重要一点是,操作员可以生成值,也可以有副作用

例如++a生成(评估为)a + 1,但它也有增加a的副作用。 a = 5也是如此(计算结果为5,同时将a的值设置为5)。

所以你在这里有两个副作用会改变a的值,这两个副作用都发生在序列点之间(可见的分号和前一个语句的结尾)。

由于运算符优先级,定义两个运算符的顺序是明确定义的,这一点无关紧要,因为处理副作用的顺序仍未定义。

因此UB。

答案 1 :(得分:3)

优先级是解析表达式的语法规则的结果。 ++优先级高于=的事实仅表示++绑定到其操作数“比=更严格”。实际上,在您的示例中,由于运算符的显示顺序,只有一种方法可以解析表达式。在诸如a = b++之类的示例中,语法规则或优先级保证这意味着与a = (b++)相同而不是(a = b)++

优先级与表达式的评估顺序或表达式的副作用的顺序几乎没有关系。 (显然,如果操作符根据语法规则操作另一个表达式 - 或优先级 - 那么必须在应用运算符之前计算该表达式的值,但是大多数独立的子表达式可以按任何顺序和侧面计算 - 效果也按任何顺序处理。)

答案 2 :(得分:1)

  

为什么是UB?

因为它试图在一个序列点之前两次更改变量a

  • ++ a
  • 运算符=

答案 3 :(得分:1)

序列点评估#6:在初始化器结束时;例如,在声明int a = 5;中评估5之后。来自维基百科。

您正尝试更改相同的变量a,两次。 ++ a更改它,赋值(=)更改它。但是,在分配结束之前,序列点尚未完成。因此,虽然它对我们来说是完全有意义的 - 标准不能保证标准能够提供正确的行为,因为标准表示不会在序列点中多次更改某些内容(简单地说)。

答案 4 :(得分:0)

它有点微妙,但可以解释为以下之一(并且编译器不知道哪个:

a=(a+1);a++;
a++;a=a;

这是因为语法中含糊不清。