GCC三元条件运算符的副作用与值计算?

Lar*_*rry 1 c gcc


我有以下代码会对我产生意外的结果:

 #include < stdio.h >

int a = 0, value;

int main(void)
{
    // Testing the evaluation order of multiple
    // conditional operators:
    value = (a == 3) ? 3 : (a = 3) ? 5 : 0;
    printf("%d\n", value);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望此代码能打印3,因为条件运算符的计算
从右到左,并且在?处有一个序列点。先执行
操作的结果,而实际上会打印出5。
假定表达式
的值是时,假设还计算了两个序列点之间的表达式的副作用,是否错误?
如果我添加printf(“%d \ n” a); 我虽然打印了3张,但副作用得到了解决。
还是只是控制剂量确实传递给了子表达式,其值
被正式“首次”计算?
我宁愿押注后者,因为将'a'的值更改为3并将右值
将第二个条件条件赋值为4导致
第一个条件表达式进行短路评估,这意味着我同时为“ a”和“ value”打印了3个值。
我使用-std = c99标志在带有GCC 4.8.2的Lubuntu 14.04上获得了上述结果。
感谢您让我澄清此事!

Mic*_*urr 6

条件运算符不会“从右到左评估”。标准(C11 6.5.15 / 4)指出:

评估第一个操作数;在它的评估与第二个或第三个操作数的评估(无论哪个被评估)之间都有一个序列点。仅当第一个比较不等于0时,才对第二个操作数求值;仅当第一个比较等于0时,才对第三个操作数求值;结果是第二个或第三个操作数的值(以所计算的为准)

因此,表达式(a == 3) ? 3 : (a = 3) ? 5 : 0;在以下步骤中求值:

  • (a == 3) 结果是 0
  • (a = 3) 结果是3,不等于0
  • 5

5分配给的也是如此value

您可能会混淆如何评估条件运算符以及条件运算符如何关联(或分组)的概念。C的语法指定表达式:

(a == 3) ? 3 : (a = 3) ? 5 : 0;
Run Code Online (Sandbox Code Playgroud)

关联或分组子表达式,如下所示:

((a == 3) ? 3 : ((a = 3) ? 5 : 0));
Run Code Online (Sandbox Code Playgroud)

通常被称为“关联权”。但是,这种分组/关联性不会影响以下事实,即仍然从左至右评估表达式,并且仅在评估“外部”条件表达式中的第一个操作数之后才评估第二个条件表达式。