简体   繁体   English

条件运算符的评估顺序

[英]Order of evaluation for conditional operator

It is known that both assignment = and conditional ?: operators have right associativity. 众所周知,赋值=和条件?:运算符都具有正确的关联性。 In following code sample: 在以下代码示例中:

#include <stdio.h>

int main(void)
{
    int a, b, c, d;

    a = b = c = d = 1;
    1 ? a++ : b ? c++ : d;

    printf("%d %d %d %d\n", a, b, c, d);
    return 0;
}

the assignment: 分配:

a = b = c = d = 1;

is equivalent to: 等效于:

a = (b = (c = (d = 1)));

and correspondingly: 并相应地:

1 ? a++ : b ? c++ : d;

is the same as: 是相同的:

1 ? a++ : (b ? c++ : d);

What the Standard say about this last case? 标准对这最后一种情况怎么说? Does it guarantee that such combined expression is evaluated from left to right (so the c++ part is not evaluated), just as opposite to assignment? 它是否保证从左到右评估这样的组合表达式(因此不评估c++部分),与赋值相反?

The evaluation order of ?: is guaranteed: the first operand is evaluated first, then evaluate the second or the third operand depending on whether the first operand is true. 保证?:的求值顺序:首先对第一个操作数求值,然后根据第一个操作数为true求值第二个或第三个操作数。

You are mainly confused about the relationship between operator precedence/associativity and order of evaluation . 您主要对运算符优先级/关联性评估顺序之间的关系感到困惑。 They play different roles. 他们扮演着不同的角色。 The former decides how operators are grouped, while the latter decides which sub-expression is evaluated first. 前者决定如何对运算符进行分组,而后者则决定首先评估哪个子表达式。

Consider the expression a * b + c * d , the precedence rule means it's equivalent to (a * b) + (c * d) . 考虑表达式a * b + c * d ,优先级规则意味着它等效于(a * b) + (c * d) But is it guaranteed that the compiler will evaluate a * b before c * d ? 但是是否可以保证编译器在c * d之前对a * b进行求值? The answer is no, in this example, the operator + doesn't guarantee the order of evaluation. 答案是否定的,在此示例中,运算符+不保证评估顺序。

The conditional operator ?: is one of the few operators that do have a specified order of evaluation. 条件运算符?:是为数不多的具有指定评估顺序的运算符之一。 (The rest are && , || , and , ). (其余的&&|| ,和, )。


In your example 在你的例子中

1 ? a++ : b ? c++ : d;
1 ? a++ : (b ? c++ : d);

are always equivalent, in both expressions, 1 is evaluated first, and since it's true, a++ is evaluated next, the end. 总是等效,在两个表达式, 1首先计算,并且因为它是真实的, a++接下来评价结束。

Associativity and precedence do not define order of evaluation . 关联性优先级未定义评估顺序 These concepts are completely unrelated. 这些概念是完全无关的。 Order of evaluation in C is defined by sequencing rules, not by precedence or associativity. C语言中的求值顺序排序规则定义,而不是由优先级或关联性定义。

It is true that a = b = c = d = 1; 确实, a = b = c = d = 1; is associated as a = (b = (c = (d = 1))); 关联a = (b = (c = (d = 1))); , but that does not mean that d = 1 should be evaluated first, especially in C language, where assignment operator evaluates to an rvalue. ,但这并不意味着应该首先评估d = 1 ,尤其是在C语言中,赋值运算符的结果为rvalue。

Associtivity simply says that c should receive value 1 converted to the type of d ("as if" it was read from d ). 关联性只是说c应该收到转换为d类型的值1 (“好像”是从d读取的)。 But that does not mean that d = 1 should be done first. 但这并不意味着d = 1应该首先完成。 In your example all variables have the same type, which means that the whole thing is equivalent to a = 1; b = 1; c = 1; d = 1; 在您的示例中,所有变量都具有相同的类型,这意味着整个对象等于a = 1; b = 1; c = 1; d = 1; a = 1; b = 1; c = 1; d = 1; in absolutely any order. 以任何顺序排列。 There's no sequencing inside a = b = c = d = 1 expression. a = b = c = d = 1表达式内部没有排序。

The same logic applies to ?: operator. 相同的逻辑适用于?:运算符。 Its associativity simply tells you which operand belongs to which operator. 它的关联性只是告诉您哪个操作数属于哪个运算符。 And the grouping is indeed 1 ? a++ : (b ? c++ : d); 分组的确是1 ? a++ : (b ? c++ : d); 1 ? a++ : (b ? c++ : d); . But associativity does not tell you anything about the order of evaluation. 但是关联性不会告诉您有关评估顺序的任何信息。 Order of evaluation in ?: operator is defined separately and independently: the condition is always evaluated (sequenced) first, then one (and only one) of the branches is evaluated. ?:运算符中的评估顺序是分别和独立定义的:始终首先评估(排序)条件,然后评估一个(只有一个)分支。 In your example 1 is evaluated first, then a++ is evaluated and its result becomes the result of the entire expression. 在您的示例1中,首先对a++求值,然后对a++求值,其结果成为整个表达式的结果。 The (b ? c++ : d) part is not even touched. (b ? c++ : d)部分甚至没有被触及。

1 ? a++ : b ? c++ : d;

is equivalent to 相当于

if (1) {
    a++;
}
else {
    if (b) {
        c++;
    }
    else {
        d;
    }
}

So, the output will be 因此,输出将是

2 1 1 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM