Abh*_*hay -1 c logical-operators pre-increment 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;
}
Run Code Online (Sandbox Code Playgroud)
我在编译器中得到的输出为:
i=1 j=-1 k=1
Run Code Online (Sandbox Code Playgroud)
但是我不明白这里到底发生了什么。
我认为if语句不应运行,因为其参数为false
注意第一个括号 (!i||--j&&k++)
因为!i=1括号中的任何一个在OR运算符下均为1 ,所以此括号为true。
输出值变为: i=0, j=-3, k=1
现在注意第二个括号: (i++||j++&&!k++)
这边有 ( 0 || -3 && !1) = 0, false
当方括号被分隔时&&,if语句的整个参数变为false。
请向我解释我的论点错了。我是C的新手
逻辑AND运算符&&和逻辑OR运算符||是短路运算符,这意味着如果可以从左侧确定表达式的结果,则不会评估右侧。
因此,当此子表达式运行时:
(!i||--j&&k++)
Run Code Online (Sandbox Code Playgroud)
解析为:
(!i||(--j&&k++))
Run Code Online (Sandbox Code Playgroud)
||评估的左侧为true,因此--j&&k++不进行评估,这意味着keeps的值j是-2,而k剩余的值是0。
所以最外面的左边&&是正确的,所以现在我们评估右边:
(i++||j++&&!k++)
Run Code Online (Sandbox Code Playgroud)
解析为:
(i++||(j++&&!k++))
Run Code Online (Sandbox Code Playgroud)
i增加到1,然后在中使用旧值||。旧值0评估为false,因此评估右侧。 j递增到-1,旧值-2评估为true,因此&&评估右侧。 k会增加到1,并将旧值0应用于!计算结果为true 的运算符。这使整个表达式为真,并打印语句,此时的i值为1,j-1和k1。
让我们稍微扩展一下,使阅读更轻松:
int i = 0, j = -2, k=0, m;
(!i || --j && k++) && (i++ || j++ && !k++)
Run Code Online (Sandbox Code Playgroud)
如您所知,它!i为true(值1),因此||为true。该||运营商是指如果左操作数是真的不评价其右操作数,所以--j && k++不评价,并没有任何影响。(正确的操作数是--j && k++因为&&优先级高于||,因此A || B && C结构为A || (B && C)。)
这解决了中央的左操作数&&。在右侧的操作数中,i++递增i为1,但求值为当前值i0,因此对于||运算符而言,它为false 。因此,||将评估该操作数的正确操作数。
该操作数为j++ && !k++。由于j是?2,因此j++更改j为?1并求值为?2,对于而言,该值为true &&。然后k++增量k1,但计算结果为0,并!k++改变它为1,产生用于真&&,并因此为先前真||和中央&&。
此时,i1 j是?1,并且k是1,这就是您得到的结果。