【问题标题】:Not getting expected output from this code using logical operators and pre/post increment使用逻辑运算符和前/后增量未从此代码获得预期输出
【发布时间】:2020-01-07 18:08:45
【问题描述】:

我在以下 C 代码中没有得到预期的输出

main(){
    int i=0,j=-2,k=0,m;

    if((!i||--j&&k++)&&(i++||j++&&!k++))
    {
        printf("i=%d j=%d k=%d",i,j,k);

    }
    return 0;
}

我在编译器中得到的输出为:

i=1 j=-1 k=1

但我不明白这里到底发生了什么。

我认为 if 语句不应该运行,因为它的参数是假的

注意第一个括号(!i||--j&&k++)

这里是!i=1,因此这个括号是真的,因为在 OR 运算符下带有 1 的任何东西都是真的。

输出值变为:i=0, j=-3, k=1

现在注意第二个括号:(i++||j++&&!k++)

这里有( 0 || -3 && !1) = 0, false

由于括号被&&分隔,if语句的整个参数变成false

请解释我的论点哪里错了。我是C新手

【问题讨论】:

标签: c logical-operators post-increment pre-increment


【解决方案1】:

逻辑 AND 运算符 && 和逻辑 OR 运算符 || 是短路运算符,这意味着如果可以从左侧确定表达式的结果,则不会计算右侧。

所以当这个子表达式运行时:

(!i||--j&&k++) 

解析为:

(!i||(--j&&k++)) 

|| 的左侧计算结果为 true,因此不计算 --j&&k++,这意味着 j 的值保持为 -2,k 的值保持为 0。

所以最外层&&的左侧为真,所以现在我们评估右侧:

(i++||j++&&!k++)

解析为:

(i++||(j++&&!k++))

i 递增到 1,然后在 || 中使用旧值。旧值 0 评估为 false,因此评估右侧。 j 递增到 -1 并且 -2 的旧值评估为 true,因此评估 && 的右侧。 k 递增到 1,旧值 0 应用于计算结果为 true 的 ! 运算符。这使得整个表达式为真并打印语句,此时 i 为 1,j 为 -1,k 为 1。

【讨论】:

    【解决方案2】:

    让我们稍微展开一下,以便于阅读:

    int i = 0, j = -2, k=0, m;
    
    (!i || --j && k++) && (i++ || j++ && !k++)
    

    您注意到!i 为真(值为1),所以|| 为真。如果左操作数为真,|| 运算符被定义为不评估其右操作数,因此--j && k++ 不会被评估并且没有效果。 (右操作数是--j && k++,因为&&的优先级高于||,所以A || B && C的结构为A || (B && C)。)

    这解决了中心&& 的左操作数。在右侧操作数中,i++i 递增到 1,但计算结果为 i 的当前值 0,因此对于 || 运算符来说它是 false。因此,|| 的右操作数被求值。

    那个操作数是j++ && !k++。由于j 为-2,j++j 更改为-1 并计算为-2,对于&& 而言,这是一个真值。然后k++k 递增到1,但计算结果为0,!k++ 将其更改为1,对&& 产生真值,因此对前一个|| 和中心&& 产生真值。

    此时i为1,j为-1,k为1,这就是你得到的结果。

    【讨论】:

      【解决方案3】:

      您可能会错过 if 语句一旦满足就结束,因此 (!i||--j&&k++) 只会计算 i 而其他操作将被忽略。我的意思是j 在第一个语句结束时将是-2。

      【讨论】:

      • 非常感谢您清除它。我有一种感觉,这就是这里发生的事情,但必须在这里发布以确保。非常感谢
      • 我会推荐“快速失败”的方法。尝试创建一个简单的文件并为较小的 if 语句打印它们的值。
      猜你喜欢
      • 2019-04-07
      • 1970-01-01
      • 2017-03-24
      • 2015-10-03
      • 1970-01-01
      • 1970-01-01
      • 2019-08-20
      • 2020-01-10
      • 2023-02-22
      相关资源
      最近更新 更多