bool型返回值函数,没写return语句的时候返回啥?
今天因为漏写了⼀个return语句,g++⼜没开warning,结果就悲剧了,调⽤的时候出现了奇怪的现象,于是就测试了⼀把到底没写return 的时候返回什么东西。
例程:
青铜葵花作者>工伤的认定标准#include <iostream>
#include <vector>
using namespace std;
bool func()
{
int i=10;
i++;
}
int main()
{
bool a = func();
bool b=true;
卡通狗狗
bool c=100;
cout<<!(a)<<endl;
cout<<!(b)<<endl;
cout<<!(c)<<endl;
cout<<(a)<<endl;
cout<<(b)<<endl;
cout<<(c)<<endl;
cout<<!10<<endl;
cout<<func()<<endl;
if(func()==true)
鸡胸肉的做法大全家常cout<<"true"<<endl;
if(func()==fal)
cout<<"fal"<<endl;
if(!func()==true)
cout<<"true"<<endl;
if(!func()==fal)
cout<<"fal"<<endl;
}
程序输出:
5
4
1
1
64
true
fal
true
fal
多次运⾏时上⾯的除0,1外的数字是随机的。
⽽且从if语句的判断当中我们可以看到当我们那这个没有返回语句的函数直接来判断时,他已经没有了bool变量的特性了。
食堂饭菜
再跟true,fal的⽐较中他们都是成⽴的。这个时候但我们不⼩⼼使⽤了if el结构的时候,就永远只会执⾏if⽽不会到el的语句中了。
所以当bool返回值的函数,在没写返回语句的时候,他并不会默认地返回⼀个true和fal,⽽是⼀个⽆定义的⾏为,会导致后⾯的判断出错。
那到底是怎么出现这样不合逻辑的现象的呢,让我们继续实验来⼀窥其中的奥秘。
要想知道其中的过程,我们⾸先⽤g++ -S来编译这份代码的汇编代码来看看。
整体汇编代码过长就不全部贴上来了,我们只来关注我们的if语句(第⼀个if语句和第⼆个)的汇编。
.L7: //第⼀个if语句
洋姜call _Z4funcv //⾸先调⽤func函数
xorl $1, %eax //将返回结果%eax与1作异或操作
testb %al, %al //判断al寄存器是否为0,这⾥的test操作就是作⼀次and,并设置标志位ZF;关于al 与eax的关系见下⾯说明。
je .L8 //根据标志位ZF作跳转。
movl $.LC0, 4(%esp)
movl $_ZSt4cout, (%esp)
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
毛泽东沁园春长沙movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
.L8: //第⼆个if语句,基本和1⼀样,但是由于和0作异或,因为作不作都⼀样,因⽽没有对应语句。
call _Z4funcv
testb %al, %al
je .L9
movl $.LC0, 4(%esp)
movl $_ZSt4cout, (%esp)
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
从 上⾯的分析中我们可以看到,但程序没有写返回语句时,我们去那返回值时,这个值就是原来返回值寄存器(eax)⾥⾯已经存在的值,这是不确定的。⽐如我们 这⾥返回了⼀个不为0,1的数字时,接下来我们进⾏bool判断时,⽆论与1异或,还是与0异或,都不会使改寄存器变0,因⽽对应的test语句也就总是 成⽴了。
法斗犬价格
我们使⽤指针去修改bool变量的值也能达到上⾯的同样的效果。⽽我们直接⽤数字去⽐较的时候却没有这个效果,是因为程序在⽐较之前会做⼀次隐性的类型转换。
附 exa, ax, ah, al 寄存器的介绍:
先请看图,图看懂了就基本解决这个了疑问了。
00000000 00000000 00000000 00000000
|===============EAX===============|--32个0,4个字节,2个字,1个双字
|======AX=======|--16个0,2个字节,1个字
|==AH===|-----------8个0,1个字节
|===AL==|---8个0,1个字节
虽说EAX是32位的寄器,但其实只是在原有的8086CPU的寄存器AX上增加了⼀倍的数据位数⽽已。故⽽EAX与AX根本不可能独⽴,⼆者是整体与部分的关系。
对EAX直接赋值,若更改了低16位⾃然会改变了AX值,⽽AX⼜可以影响EAX整体。⽽AH,AL寄存器
和AX之间的关系也是如此。