众所周知,赋值=
和条件?:
运算符都具有正确的关联性。在以下代码示例中:
#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;
}
作业:
a = b = c = d = 1;
相当于:
a = (b = (c = (d = 1)));
并相应地:
1 ? a++ : b ? c++ : d;
与:
相同1 ? a++ : (b ? c++ : d);
标准对最后一个案例的看法是什么?它是否保证从左到右评估这样的组合表达式(因此不评估c++
部分),与赋值相反?
答案 0 :(得分:6)
保证?:
的评估顺序:首先计算第一个操作数,然后根据第一个操作数是否为真来计算第二个或第三个操作数。
您对运算符优先级/关联性与评估顺序之间的关系感到困惑。他们扮演不同的角色。前者决定如何对运算符进行分组,而后者决定首先计算哪个子表达式。
考虑表达式a * b + c * d
,优先规则意味着它等同于(a * b) + (c * d)
。但是保证编译器会在a * b
之前评估c * d
吗?答案是否定的,在本例中,运营商+
并不保证评估顺序。
条件运算符?:
是具有指定评估顺序的少数运算符之一。 (其余为&&
,||
和,
)。
在你的例子中
1 ? a++ : b ? c++ : d;
1 ? a++ : (b ? c++ : d);
始终是等效的,在两个表达式中,首先评估1
,并且由于它是真的,接下来评估a++
,结束。
答案 1 :(得分:3)
关联性和优先级不定义评估顺序。这些概念完全不相关。 C中的评估顺序由排序规则定义,而不是由优先级或关联性定义。
a = b = c = d = 1;
关联确实是a = (b = (c = (d = 1)));
,但这并不意味着应首先评估d = 1
,尤其是在C语言中,赋值运算符求值为右值。
关联性只是说c
应该收到转化为1
类型的值d
(“好像”它是从d
读取的)。但这并不意味着应该首先完成d = 1
。在您的示例中,所有变量都具有相同的类型,这意味着整个事物绝对等同于a = 1; b = 1; c = 1; d = 1;
。 a = b = c = d = 1
表达式中没有排序。
同样的逻辑适用于?:
运算符。它的关联性只是告诉你哪个操作数属于哪个操作符。分组确实是1 ? a++ : (b ? c++ : d);
。但是,关联性并没有告诉你关于评估顺序的任何信息。 ?:
运算符中的评估顺序是单独和独立定义的:首先评估条件(排序),然后评估一个(并且只有一个)分支。在您的示例中,首先评估1
,然后评估a++
,其结果将成为整个表达式的结果。 (b ? c++ : d)
部分甚至没有触及。
答案 2 :(得分:1)
1 ? a++ : b ? c++ : d;
相当于
if (1) {
a++;
}
else {
if (b) {
c++;
}
else {
d;
}
}
因此,输出将是
2 1 1 1