GCC三元条件算子中的副作用与值计算?

时间:2014-09-15 19:54:21

标签: 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;
}

我期待这个代码打印3,看到条件运算符评估
从右到左,有一个序列点?第一次执行的 操作,而它实际打印5.
假设表达式的副作用位于两个序列之间是不对的 当表达式的值为?时,也会计算得分 如果我添加printf(“%d \ n”a);我打印了3张,所以副作用就完成了 或者仅仅是控制剂量确实传递给子表达式的值 是正式计算“第一”? 我宁愿赌后者,因为将'a'的值改为3和rvalue
在第二条件赋值给4时导致短路评估 第一个条件表达式,意味着我为'a'和'value'打印了3个。
我使用-std = c99标志在带有GCC 4.8.2的Lubuntu 14.04上得到了上述结果 感谢有人在这件事上解决我的问题!

3 个答案:

答案 0 :(得分:4)

条件运算符不会从右到左评估&#34;。标准(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;

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

((a == 3) ? 3 : ((a = 3) ? 5 : 0));

通常被描述为&#39;关联正确&#39;。但是,这种分组/关联性并不会影响这样一个事实,即表达式仍然是从左到右进行评估,而第二个条件表达式仅在“外部”的第一个操作数之后进行评估。评估条件表达式。

答案 1 :(得分:0)

让我们一次追踪这一部分。你有这个表达:

value = (a == 3) ? 3 : (a = 3) ? 5 : 0;

由于a从0开始,我们跳过第一个3的{​​{1}}分支并查看第二个分支,即

?:

这里的条件是(a = 3) ? 5 : 0 ,它将a = 3设置为3,然后计算为a的新值,即3.因为3非零,我们取第一个分支a的表达式,因此表达式的计算结果为?:。实际效果是5设置为3,a设置为5。

语言规范保证评估顺序确实是您认为的应该是 - &#34; if&#34;和&#34;否则&#34;保证value运算符的分支不会执行,除非条件成功,因此这里有序列点。我想你只是误解了?:操作的效果。

希望这有帮助!

答案 2 :(得分:0)

条件运算符从左到右进行求值(在任一分支之前评估条件)。你可能会把它与它的右关联性混淆(它似乎从右到左绑定)。

您的条件表达式实际上会产生以下逻辑:

if(a == 3) {
    value = 3;
} else {
    if(a = 3) {
        value = 5;
    } else {
        value = 0;
    }
}

请注意,条件在评估条件之后才会执行分支。

相关问题