1

我想问一个关于下面代码的问题。

int a=1, b=3, c=1;

if((a||c--)&&(c&&b--)) printf("%d",b);
printf("%d %d %d",a,b,c);

为什么代码打印“21 2 1”而不是“1 2 0”?

谢谢你的帮助。

4

3 回答 3

3

由于 or 在 (a||c--) 中立即被评估为真,因此 c-- 永远不会被评估。编译器会这样做。如果一个陈述立即成立,它就不会费心评估其余部分。因此, c 永远不会递减,因为 or 的右侧永远不会被评估。

于 2021-02-03T21:33:08.467 回答
1

你可以想象这个 if 语句

if((a||c--)&&(c&&b--)) printf("%d",b);

以下方式

if ( a )
{
    if ( c )
    {
        if ( b-- )
        {
            printf("%d",b);
        }
    }
}
else if ( c-- )
{
    if ( c )
    {
        if ( b-- )
        {
            printf("%d",b);
        }
    }
}

所以如果第一个 if 语句中的表达式

if ( a )

评估为逻辑真然后这个 if 语句

else if ( c-- )

永远无法控制。

来自 C 标准(6.5.14 逻辑或运算符)

4 不同于按位 | 运算符,|| 运算符保证从左到右的评估;如果计算第二个操作数,则在第一个和第二个操作数的计算之间存在一个序列点。如果第一个操作数比较不等于 0,则不计算第二个操作数

于 2021-02-03T21:45:42.620 回答
1

两者||&&强制从左到右评估 - 首先评估 LHS并应用所有副作用,然后根据结果评估 RHS。

两个运算符短路:

  • 对于a || b,如果a不为零,则表达式的结果与1的值无关b,因此b不计算;
  • 对于a && b,如果a为零,则表达式的结果与0的值无关b,因此b不计算。

&&优先级高于||,因此a || b && c被解析为a || (b && c)

将所有这些放在一起,(a||c--)&&(c&&b--)评估如下:

  1. a || c--评估如下:
    1. a被评估 - 它的结果是1,所以
    2. c--评估;因为 thisc的值没有改变,并且
    3. 表达式的结果是1
  2. c && b--评估如下:
    1. c被评估 - 它的结果是1,所以
    2. b--被评估 - 它的结果是3; 作为副作用 b减少,和
    3. 表达式的结果是1
  3. 两者a || c--c && b--评估为1

a和的值c不变(分别为11),而b已递减,其值为 now 2

于 2021-02-03T22:07:48.317 回答