时光20 发表于 2018-10-26 09:40:21

这个逻辑与运算是怎样优化的 求告知 感谢!


   RT:
#include<stdio.h>
void main()
{
        int a=0,b=2,c;
        c=!a||++b&&a--;
        printf("%d,%d,%d\n",a,b,c);
}

结果:0,2,1

上面是编译器运行的结果
但是 我觉得 结果应该是:a=-1,b=3,c=1
所以有点不明白 与运算和自增自减 在这里是怎么优化的
希望各位鱼油指教,谢谢!{:10_254:} {:10_287:}

1005204767 发表于 2018-10-26 09:49:42

为什么b不自增呢?

pheron 发表于 2018-10-26 09:56:46

本帖最后由 pheron 于 2018-10-26 10:22 编辑

我觉得楼下说的对

风扫地 发表于 2018-10-26 10:02:43

本帖最后由 风扫地 于 2018-10-27 08:59 编辑

可能和短路原则有关。
因为你的 !a||++b&&a--代码里面没括号,我不熟悉结合关系和计算顺序(学的时候弄明白就行,因为考试肯定要考,但确实很难记住那么多运算符的结合顺序和优先级,在工作工程中必须用小括号明确运算结合关系和运算顺序),不具体分析。
短路原则是指:
对于 &&|| 这两个运算符,
若 a && b 中的a已经为0,b就不算了,因为0 && x = 0
若 a || b 中的a已经为1,b就不算了,因为 1 || x = 1



Ref:
https://bbs.csdn.net/topics/190096722
https://fishc.com.cn/forum.php?mod=viewthread&tid=93862&highlight=%B6%CC%C2%B7

1005204767 发表于 2018-10-26 10:24:56

嗷嗷记起来了
&&和||语句的判断都是从左至右的。
即a && b会先判断a,如果a为True,则还需要判断b的Boolean值,不管b的Boolean值是什么,最后一个判断的是b,所以会输出b的Boolean值;反之,如果a为False,则不需要再判断b的Boolean值了,因为结果肯定为False,所以最后进行判断的就是a,也就是会输出a的Boolean值。
而a || b也是会先判断a,如果a的Boolean值为True,则不需要再判断b的Boolean值了,因为结果肯定是True了,也就是会输出a的Boolean值;如果a的Boolean值为False,则就需要再去判断b的Boolean值,不管b的Boolean值为多少,最后进行判断的都是b,也就是输出就为b的Boolean值。

回访三生 发表于 2018-10-26 15:05:46

//为了回答这道题,以下以C注释形式分析以下汇编代码
#include<stdio.h>
void main()
{
010F13C0push      ebp
010F13C1mov         ebp,esp
010F13C3sub         esp,0E8h
010F13C9push      ebx
010F13CApush      esi
010F13CBpush      edi
010F13CClea         edi,
010F13D2mov         ecx,3Ah
010F13D7mov         eax,0CCCCCCCCh
010F13DCrep stos    dword ptr es:
        int a = 0, b = 2, c;
010F13DEmov         dword ptr ,0
010F13E5mov         dword ptr ,2
//以上代码与问题无关不做解释
//------------------------------------------完美分割线--------------------------------------
        c = !a || ++b && a--;
//以下两句为!a计算并实现||运算符的短路原则
010F13ECcmp         dword ptr ,0                //将a与0比较
010F13F0je          main+59h (010F1419h)         //a为0则跳到地址010F1419h处,其实这里就直接跳转了,从这道010F1419h代码都没执行

//以下三句为++b实现代码
010F13F2mov         eax,dword ptr         //将b内存中的值移动到寄存器eax中
010F13F5add         eax,1                        //eax寄存器自加1
010F13F8mov         dword ptr ,eax        //将eax的值移动回到b内存处

//当b为0则跳到010F140Dh处,不为0则继续
010F13FBje          main+4Dh (010F140Dh)

//以下四句位为a--对应代码
010F13FDmov         ecx,dword ptr         //a移动到ecx寄存器(备份a的值,以便后序判断使用)
010F1400mov         edx,dword ptr         //a移动到edx寄存器
010F1403sub         edx,1                        //edx-1
010F1406mov         dword ptr ,edx        //将edx存会a

//ecx为刚才对a的备份,以下一句测试原来的a值是否为0,也就是实现后 -- 的先使用后自减的特性
010F1409test      ecx,ecx
010F140Bjne         main+59h (010F1419h)//原a不为0则表示逻辑与 && 成立, 跳到010F1419h

//原a为0则逻辑与表达式为假
010F140Dmov         dword ptr ,0                //用一个临时变量来存放记过(ebp-0E8h)
010F1417jmp         main+63h (010F1423h)                //跳到010F1423h处

//原a不为0则表达式为真将1赋值到临时变量
010F1419mov         dword ptr ,1

//将临时变量赋值个c变量
010F1423mov         eax,dword ptr
010F1429mov         dword ptr ,eax

//以下调用printf函数,不做解释
//---------------------------------------------完美分割线再现----------------------------------------
        printf("%d,%d,%d\n", a, b, c);
010F142Cmov         esi,esp
010F142Emov         eax,dword ptr
010F1431push      eax
010F1432mov         ecx,dword ptr
010F1435push      ecx
010F1436mov         edx,dword ptr
010F1439push      edx
010F143Apush      10F5858h
010F143Fcall      dword ptr ds:
010F1445add         esp,10h
010F1448cmp         esi,esp
010F144Acall      __RTC_CheckEsp (010F1136h)        //堆栈平衡检测
}

wjp 发表于 2018-10-27 05:24:42

因为!a一定为真,所以||后面的代码都不执行了,好像是叫短路原则

wwhywhy 发表于 2018-10-27 10:10:08

短路原则,竟然这么神奇!又学习了。

时光20 发表于 2018-10-27 11:47:58

在这里谢过各位鱼油了 么么哒
{:10_281:}
页: [1]
查看完整版本: 这个逻辑与运算是怎样优化的 求告知 感谢!