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

  • 本文关键字:之间 操作符 优先级 c++
  • 更新时间 :
  • 英文 :


我举个例子:

a = ++a;

上面的语句据说有未定义的行为(我已经阅读了关于UB on SO的文章)

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

所以a应该先加,然后再赋值给a.所以每个评估都是已知的,所以为什么是UB ?

这里需要理解的重要一点是,操作符可以产生值,也可以产生副作用

例如,++a产生(求值为)a + 1,但它也有增加a的副作用。a = 5也是如此(求值为5,也将a的值设置为5)。

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

由于操作符优先,两个操作符的求值顺序是定义好的,这并不重要,因为处理它们的副作用的顺序仍然是未定义的。

优先级是解析表达式的语法规则的结果。++=具有更高的优先级这一事实仅仅意味着++与它的操作数的绑定比="更紧密"。实际上,在您的示例中,由于操作符出现的顺序,只有一种方法可以解析表达式。在像a = b++这样的例子中,语法规则或优先级保证它的含义与a = (b++)相同,而不是(a = b)++

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

为什么是UB ?

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

  • + +
  • 操作符=

序列点求值#6:在初始化式结束时;例如,在int声明中求值5后,a = 5;从维基百科。

你试图改变同一个变量a两次。++a改变了它,赋值(=)也改变了它。但是序列点直到赋值结束时才完成。因此,虽然这对我们来说是完全有意义的,但标准并不能保证提供正确的行为,因为标准规定在一个序列点(简单地说)中不要多次更改某些内容。

这有点微妙,但它可以被解释为以下其中一种(编译器不知道是哪一种):

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

最新更新