赋值子表达式的评估顺序

问题描述 投票:1回答:3

The C++11 standard(5.17,expr.ass)表示

在所有情况下,在右和左操作数的值计算之后,以及在赋值表达式的值计算之前,对赋值进行排序。对于不确定序列的函数调用,复合赋值的操作是单个评估

这是否意味着,表达式:

int a = 1, b = 10;
int c = (a+=1) + (b+=1);

if ( c == 10+1+1+1 ) {
    printf("this is guaranteed");
} else {
    printf("not guaranteed"); 
}

总会评价到c==23

c++ c++11 variable-assignment operator-precedence
3个回答
1
投票

这一直是有保证的,并且规则之前的顺序(或前C ++ 11中的序列点规则)不需要确定这一点。在C ++中,每个(子)表达式在生成的代码中有两个重要的影响:它有一个值(除非它是void类型),它可能有副作用。排序的前/序列点规则影响何时保证发生副作用;它们对子表达式的值没有影响。例如,在您的情况下,(a += 1)的值是a在赋值后将具有的值,无论实际赋值何时发生。

在C ++ 11中,a的实际修改保证在修改c之前进行;在预C ++ 11中,没有关于订单的保证。然而,在这种情况下,合规程序无法看到这种差异,因此无关紧要。 (在像c = (c += 1)这样的情况下会很重要,这在C ++ 11之前会是未定义的行为。)


2
投票

表达方式

int c = (a+=1) + (b+=1);

(编辑:添加了缺少的括号,我认为这是你的意图)

有以下子表达式

(1) a+=1
(2) b+=1
(3) (1)+(2)
(4) c = (3)

未指定评估(1)和(2)的顺序,编译器可以自由选择它喜欢的任何顺序。

在编译器可以评估(3)之前,必须评估(1)和(2)。

(3)必须在编译器评估之前进行评估(4)。

现在,由于(1)和(2)的评估顺序无关紧要,整体结果已明确定义,您的代码将始终产生13并打印“这是现在的标准”。请注意,这一直是这样,这对于C ++ 11来说并不新鲜。


1
投票

在您的示例中,编译器应发出错误,因为加法运算符的优先级高于赋值运算符的优先级。因此,首先计算1 + b,然后尝试将1分配给表达式(1 + b),但(1 + b)不是左值。

© www.soinside.com 2019 - 2024. All rights reserved.