C函数定义为int但在正文中没有返回语句仍然编译

时间:2010-11-23 19:37:18

标签: c compilation

假设您有这样的C代码:

#include <stdio.h>

int main(){
    printf("Hello, world!\n");
    printf("%d\n", f());    
}

int f(){

}

用gcc编译好,输出(在我的系统上)是:

  

你好,世界!

     

14

但是......但是......这怎么可能?我认为C不会让你编译那样的东西因为f()没有返回整数的return语句。为什么允许这样做?它是C特征还是编译器遗漏,14来自哪里?

7 个答案:

答案 0 :(得分:17)

在这种情况下,返回值取决于确切的平台,可能是在汇编级别的返回寄存器中发生的任何随机值(例如x86上的EAX)。不允许显式返回值,但会给出未定义的值。

在这种情况下,14是printf的返回值。

答案 1 :(得分:9)

使用-Wall进行编译,以便在编译器中启用更多的健全性检查。

gcc -Wall /tmp/a.c
/tmp/a.c: In function ‘main’:
/tmp/a.c:5: warning: implicit declaration of function ‘f’
/tmp/a.c:6: warning: control reaches end of non-void function
/tmp/a.c: In function ‘f’:
/tmp/a.c:10: warning: control reaches end of non-void function

注意它是如何标记缺少的返回语句 - 因为“控制到达非空函数的结尾”?

始终使用-Wall或类似方法进行编译 - 稍后您将为自己省心。


我可以回想一下,当这个确切的问题导致几小时或几天的调试修复时,我可以回想起它 - 直到有一天它才会有效。

答案 2 :(得分:4)

14也是第一个printf的返回值。也许,编译器优化了对f()的调用,然后我们在EAX上留下了14。

尝试使用不同的优化级别(-O0,-O1,-O2,-O3,-Os)编译代码,并查看输出是否发生变化。

答案 3 :(得分:2)

18是第一个print语句的返回值。 (打印的字符数)

该值存储在堆栈存储器中。

在第二个printf函数中,函数f'返回'堆栈值。但是f只是将printf在堆栈中创建的值保留在堆栈中。

例如,在此代码中:

#include <stdio.h>

int main(){
    printf("Hello, world!1234\n");
    printf("%d\n", f());    
}

int f(){

}

使用gcc编译好,输出(在我的系统上)是:

  

你好,世界!

     

18

有关printf()返回值邮寄给我的详细信息。

答案 4 :(得分:1)

  

a的默认返回值   function是int。换一种说法,   除非明确指明了   编译器的默认返回值   是函数的整数值。

因此,允许省略return语句,但如果您尝试使用它,将返回未定义的值。

答案 5 :(得分:1)

您的编译器集的警告级别可能非常低。因此,即使结果未定义,也允许这样做。

答案 6 :(得分:0)

我使用-Werror=return-type进行编译以防止这种情况发生。如果您不从函数返回,GCC将给出错误(除非它返回无效)。