突然好奇两个无关紧要的问题,一个是,在汇编层面,int是怎么转成bool类型的;一个是if中直接对int类型变量进行判断,中间是怎么处理的?
源码:
int main() {
int a = 10;
bool b = false;
b = a;
}
反汇编:
Dump of assembler code for function main:
0x00000000004005b0 <+0>: push %rbp
0x00000000004005b1 <+1>: mov %rsp,%rbp
0x00000000004005b4 <+4>: movl $0xa,-0x4(%rbp)
0x00000000004005bb <+11>: movb $0x0,-0x5(%rbp)
0x00000000004005bf <+15>: cmpl $0x0,-0x4(%rbp)
0x00000000004005c3 <+19>: setne %al
0x00000000004005c6 <+22>: mov %al,-0x5(%rbp)
0x00000000004005c9 <+25>: mov $0x0,%eax
0x00000000004005ce <+30>: pop %rbp
0x00000000004005cf <+31>: retq
End of assembler dump.
可以看到,%rbp-0x4中用4个字节存的a,%rbp-0x5中用一个字节存的b,而%al最后赋值给了b,类型转换的代码就在这两行:
0x00000000004005bf <+15>: cmpl $0x0,-0x4(%rbp) //比较0和变量a的值,也就是a-0
0x00000000004005c3 <+19>: setne %al // 结果不是0就设为1,结果是0就设为0
所以,int转bool是通过一个int和0的比较指令,来完成的。
源码:
int main() {
int a = 10;
bool b = false;
if (a)
b = true;
if (b)
a = 20;
}
反汇编:
Dump of assembler code for function main:
0x00000000004005b0 <+0>: push %rbp
0x00000000004005b1 <+1>: mov %rsp,%rbp
0x00000000004005b4 <+4>: movl $0xa,-0x8(%rbp)
0x00000000004005bb <+11>: movb $0x0,-0x1(%rbp)
0x00000000004005bf <+15>: cmpl $0x0,-0x8(%rbp)
0x00000000004005c3 <+19>: je 0x4005c9 <main+25>
0x00000000004005c5 <+21>: movb $0x1,-0x1(%rbp)
0x00000000004005c9 <+25>: cmpb $0x0,-0x1(%rbp)
0x00000000004005cd <+29>: je 0x4005d6 <main+38>
0x00000000004005cf <+31>: movl $0x14,-0x8(%rbp)
0x00000000004005d6 <+38>: mov $0x0,%eax
0x00000000004005db <+43>: pop %rbp
0x00000000004005dc <+44>: retq
End of assembler dump.
核心的两条比较指令在:
cmpl $0x0,-0x8(%rbp)
cmpb $0x0,-0x1(%rbp)
分别对应if(a)和if(b),可以看到,不管是直接拿一个int值来作为判断,还是拿bool,都是有一条比较指令的,只是比较的字节数不一样,一个比较4字节,一个比较1字节。但是都是一条指令,效率上是等价的。
综上,直接拿int值作为判断,效率、效果实际上和先显式转换成bool再判断是一样的。反倒是显式转换要多两条转换指令。