带返回值的函数没写return语句时返回什么 您所在的位置:网站首页 js函数没有返回值会输出之前存储的值吗为什么 带返回值的函数没写return语句时返回什么

带返回值的函数没写return语句时返回什么

2024-07-17 03:22| 来源: 网络整理| 查看: 265

2013-07-02 18:44:12

转自:http://bbs.chinaunix.net/thread-1363165-1-1.html

问题描述:

如题,例如我有int f(int x){    if(x==2)return 1;//x不等于2的时候没有相应的返回语句} main(...){...   printf("%d\n",f(3)); ...}这里printf的输出结果是个很奇怪的数,而且每次都一样!

我想知道,既然f要求返回一个整数,那么在有的路径下没有显示的写return语句,这个return的值是编译器默认生成的吗? 还是返回了堆栈上的某个东西,实际上破坏了堆栈可能导致未定义的结果呢?

还请dx指点!

解答:

如果你给 IA-32 平台生成代码,一般函数的返回值是放在 [e]ax 寄存器里的,不管你的 return 带值与否,通用寄存器里总有一个值,这个值可能不具任何意义。

 

关于main函数不声明返回值为int,或者main函数体无显式return或exit语句时的情况,APUE7.3节有详细讨论,不同的平台结果也是不一样的

 

 

拿你的问题来说int f(int x){    if(x==2)return 1;//x不等于2的时候没有相应的返回语句}main(...){...   printf("%d\n",f(3));...} printf函数中使用的f(3)的值实际上就是eax寄存器的值

如果函数f确实返回1,则会将1存入eax寄存器并返回但是此时由于函数f并不执行if(x==2)return 1语句,所以实际上eax寄存器的值在执行函数f时保存不变,直接返回

main函数在执行printf之前使用了寄存器eax,它里面是什么值,最终打印出来的就是什么值

我的环境:Windows XP + MinGW gcc 3.4.2结果是16384

 

转自:http://blog.csdn.net/junchaox/article/details/7878277

转载网址:http://hi.baidu.com/pope123/blog/item/7c9315f7630b6630730eec79.html

今天因为漏写了一个return语句,g++又没开warning,结果就悲剧了,调用的时候出现了奇怪的现象,于是就测试了一把到底没写return的时候返回什么东西。

例程:

#include #include using namespace std;bool func(){    int i=10;    i++;}int main(){bool a = func();bool b=true;bool c=100;coutcoutcout

}

程序输出:

5 00411064truefalsetruefalse

多次运行时上面的除0,1外的数字是随机的。

而且从if语句的判断当中我们可以看到当我们那这个没有返回语句的函数直接来判断时,他已经没有了bool变量的特性了。

再跟true,false的比较中他们都是成立的。这个时候但我们不小心使用了if else结构的时候,就永远只会执行if而不会到else的语句中了。

所以当bool返回值的函数,在没写返回语句的时候,他并不会默认地返回一个true和false,而是一个无定义的行为,会导致后面的判断出错。

 

那到底是怎么出现这样不合逻辑的现象的呢,让我们继续实验来一窥其中的奥秘。

要想知道其中的过程,我们首先用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_PKcmovl    $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)movl    %eax, (%esp)call    _ZNSolsEPFRSoS_E

.L8:                                  //第二个if语句,基本和1一样,但是由于和0作异或,因为作不作都一样,因而没有对应语句。call    _Z4funcvtestb   %al, %alje  .L9movl    $.LC0, 4(%esp)movl    $_ZSt4cout, (%esp)call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKcmovl    $_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之间的关系也是如此。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有