使用逻辑运算符和 pre/post 增量未从此代码获得预期输出

Not getting expected output from this code using logical operators and pre/post increment

我在以下 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 语句不应该 运行 因为它的参数是 false

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

此处为 !i=1 因此此括号为真,因为 OR 运算符下带有 1 的任何内容都为真。

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

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

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

由于括号被&&隔开,if语句的整个参数变为false.

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

您可能错过了 if 语句一旦满足就结束,所以 (!i||--j&&k++) 只会计算 i 而其他操作将被忽略。我的意思是 j 将在第一个语句结束时变为 -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,因此对于 || 运算符而言它为假。所以 || 的右操作数被评估。

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

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

逻辑与运算符&&和逻辑或运算符||是短路运算符,这意味着如果表达式的结果可以从左侧。

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

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

解析为:

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

|| 的左侧计算结果为真,因此 --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。