鱼C论坛

 找回密码
 立即注册
查看: 3396|回复: 18

关于c语言中的短路求值

[复制链接]
发表于 2020-2-25 18:20:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
&&左右两边同时为真才为真,一侧为假即假,如果左侧为假,右侧直接跳过进入下一句
||左右两边任一边为真即为真,同时为假才为假,如果左侧为真,右侧直接跳过进入下一句

e.g. 先执行括号内的内容(程序由左向右执行判断完左侧真假至&&处就自动跳过右侧,即使右侧优先级高于&&)
        a = 0 --> && false(跳过)
        输出 a = 0(已给a赋值)
                b = 3(原来定义的值)
        a = 3 --> && true(赋值)
        b = 5 --> && true(赋值)
        输出 a = 3, b = 5
        a = 0 --> || false(跳过)为什么这里左为假右为真,右侧却被跳过了?
        输出 a = 0, b = 5(上一次赋值的值)
        a = 1 --> || true(跳过)
        输出 a = 1, b = 5(被跳过,保持不变)
#include <stdio.h>

int main()
{
        int a = 1;
        int b = 3;
        (a = 0) && (b = 5);
        printf("a = %d, b = %d\n", a, b);
        (a = 3) && (b = 5);
        printf("a = %d, b = %d\n", a, b);
        (a = 0) || (b = 4);
        printf("a = %d, b = %d\n", a, b);
        (a = 1) || (b = 6);
        printf("a = %d, b = %d\n", a, b);

        return 0;
}
结果为:
a = 0, b = 3
a = 3, b = 5
a = 0, b = 5
a = 1, b = 5
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-2-26 20:23:39 | 显示全部楼层
我的编译器出了点毛病,问题已解决
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 18:22:43 | 显示全部楼层
= 是赋值运算符  == 才是判断
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2020-2-25 18:25:06 | 显示全部楼层
a = 0, b = 3
a = 3, b = 5
a = 0, b = 4
a = 1, b = 4
我这里是这样的(Dev-C++)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 18:25:35 | 显示全部楼层
qiuyouzhi 发表于 2020-2-25 18:25
我这里是这样的(Dev-C++)

你用的是什么编译器?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 18:27:55 | 显示全部楼层
一个账号 发表于 2020-2-25 18:25
你用的是什么编译器?

Dev-C++的GCC啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 18:29:15 | 显示全部楼层


Dev - C++ 的默认编译器是 GCC 吗?我不知道
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 18:30:04 | 显示全部楼层
一个账号 发表于 2020-2-25 18:29
Dev - C++ 的默认编译器是 GCC 吗?我不知道

TDM-GCC 4.8.1 64-bit Release
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 21:46:45 | 显示全部楼层
你的操作是赋值,不是判断呀,判断是用==来对比
我用VC6.0反编译
9:        int a = 1;
0040D748 C7 45 FC 01 00 00 00 mov         dword ptr [ebp-4],1
10:       int b = 3;
0040D74F C7 45 F8 03 00 00 00 mov         dword ptr [ebp-8],3
11:       (a = 0) && (b = 5);
0040D756 C7 45 FC 00 00 00 00 mov         dword ptr [ebp-4],0
0040D75D 83 7D FC 00          cmp         dword ptr [ebp-4],0
0040D761 74 07                je          main+3Ah (0040d76a)
0040D763 C7 45 F8 05 00 00 00 mov         dword ptr [ebp-8],5
12:       printf("a = %d, b = %d\n", a, b);
0040D76A 8B 45 F8             mov         eax,dword ptr [ebp-8]
0040D76D 50                   push        eax
0040D76E 8B 4D FC             mov         ecx,dword ptr [ebp-4]
0040D771 51                   push        ecx
0040D772 68 AC 2F 42 00       push        offset string "a = %d, b = %d\n" (00422fac)
0040D777 E8 24 39 FF FF       call        printf (004010a0)
0040D77C 83 C4 0C             add         esp,0Ch
13:       (a = 3) && (b = 5);
0040D77F C7 45 FC 03 00 00 00 mov         dword ptr [ebp-4],3
0040D786 83 7D FC 00          cmp         dword ptr [ebp-4],0
0040D78A 74 07                je          main+63h (0040d793)
0040D78C C7 45 F8 05 00 00 00 mov         dword ptr [ebp-8],5
14:       printf("a = %d, b = %d\n", a, b);
0040D793 8B 55 F8             mov         edx,dword ptr [ebp-8]
0040D796 52                   push        edx
0040D797 8B 45 FC             mov         eax,dword ptr [ebp-4]
0040D79A 50                   push        eax
0040D79B 68 AC 2F 42 00       push        offset string "a = %d, b = %d\n" (00422fac)
0040D7A0 E8 FB 38 FF FF       call        printf (004010a0)
0040D7A5 83 C4 0C             add         esp,0Ch
15:       (a = 0) || (b = 4);
0040D7A8 C7 45 FC 00 00 00 00 mov         dword ptr [ebp-4],0
0040D7AF 83 7D FC 00          cmp         dword ptr [ebp-4],0
0040D7B3 75 07                jne         main+8Ch (0040d7bc)
0040D7B5 C7 45 F8 04 00 00 00 mov         dword ptr [ebp-8],4
16:       printf("a = %d, b = %d\n", a, b);
0040D7BC 8B 4D F8             mov         ecx,dword ptr [ebp-8]
0040D7BF 51                   push        ecx
0040D7C0 8B 55 FC             mov         edx,dword ptr [ebp-4]
0040D7C3 52                   push        edx
0040D7C4 68 AC 2F 42 00       push        offset string "a = %d, b = %d\n" (00422fac)
0040D7C9 E8 D2 38 FF FF       call        printf (004010a0)
0040D7CE 83 C4 0C             add         esp,0Ch
17:       (a = 1) || (b = 6);
0040D7D1 C7 45 FC 01 00 00 00 mov         dword ptr [ebp-4],1
0040D7D8 83 7D FC 00          cmp         dword ptr [ebp-4],0
0040D7DC 75 07                jne         main+0B5h (0040d7e5)
0040D7DE C7 45 F8 06 00 00 00 mov         dword ptr [ebp-8],6
18:       printf("a = %d, b = %d\n", a, b);
0040D7E5 8B 45 F8             mov         eax,dword ptr [ebp-8]
0040D7E8 50                   push        eax
0040D7E9 8B 4D FC             mov         ecx,dword ptr [ebp-4]
0040D7EC 51                   push        ecx
0040D7ED 68 AC 2F 42 00       push        offset string "a = %d, b = %d\n" (00422fac)
0040D7F2 E8 A9 38 FF FF       call        printf (004010a0)
0040D7F7 83 C4 0C             add         esp,0Ch
它这个短路好像是 &&或者 || 的左值与0进行一个比较,也就是a进行判断,其实a无非就两种可能0与非0,0是false 非0是true

然后根据
逻辑与 &&
&& 操作符的左操作数总是首先进行求值, 如果它的值为真, 则继续计算右操作数的值, 然后执行与操作得到表达式结果; 如果它的值为假, 根据与操作 有假则假 的性质可以断定该表达式的值为假, 所以不再计算右操作数的值.

逻辑或 ||
|| 操作符的左操作数也是首先进行求值, 如果它的值为假, 则继续计算右操作数的值, 然后执行与操作得到表达式结果; 如果它的值为真, 根据或操作 有真则真 的性质可以断定该表达式的值为真, 所以不再计算右操作数的值.
        (a = 0) && (b = 5);  //a=0 假 短路返回 
        printf("a = %d, b = %d\n", a, b);
        (a = 3) && (b = 5);  //a=3 真 不短路
        printf("a = %d, b = %d\n", a, b);
        (a = 0) || (b = 4);  //a=0 假  不短路   
        printf("a = %d, b = %d\n", a, b);
        (a = 1) || (b = 6); //a=0 假  短路返回  
        printf("a = %d, b = %d\n", a, b);

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 22:21:00 | 显示全部楼层
4goodworld 发表于 2020-2-25 21:46
你的操作是赋值,不是判断呀,判断是用==来对比
我用VC6.0反编译

怎么用 VC 6.0 反编译?Dev-C++ 能反编译吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-25 22:38:09 | 显示全部楼层
一个账号 发表于 2020-2-25 22:21
怎么用 VC 6.0 反编译?Dev-C++ 能反编译吗?

可能表述上不够精准,应该是vc6.0查看汇编代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-26 11:29:26 | 显示全部楼层
左边是假的,右边就不会赋值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-26 18:23:00 | 显示全部楼层
cc123hh 发表于 2020-2-26 11:29
左边是假的,右边就不会赋值

不是&&才有这样的性质吗,||不是左边为假再判断右边吗,可我这个||左边为假,然后它右边就跳过赋值了,b的值还是5.您再看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-26 18:25:15 | 显示全部楼层
qiuyouzhi 发表于 2020-2-25 18:25
我这里是这样的(Dev-C++)

对啊,我就认为是这样的,但是我输出的时候有错误出现
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-26 18:25:58 | 显示全部楼层
一个账号 发表于 2020-2-25 18:25
你用的是什么编译器?

vs2019community
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-26 18:35:40 | 显示全部楼层
4goodworld 发表于 2020-2-25 21:46
你的操作是赋值,不是判断呀,判断是用==来对比
我用VC6.0反编译

我的可能编译器出了点毛病
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-26 20:58:18 | 显示全部楼层
黑旋风君 发表于 2020-2-26 18:23
不是&&才有这样的性质吗,||不是左边为假再判断右边吗,可我这个||左边为假,然后它右边就跳过赋值了,b ...

额我也不是很懂,我记得||和&&好像是一样的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-27 21:34:32 | 显示全部楼层
cc123hh 发表于 2020-2-26 20:58
额我也不是很懂,我记得||和&&好像是一样的

不好意思啊,是我编译器出毛病了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-28 13:46:54 | 显示全部楼层
emmmm
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-15 23:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表