C语言中未显式return的函数为何printf能输出对应值?
C语言非void函数无return语句返回值现象说明
示例代码
#include <stdio.h> int fun1(void); int fun2(void); int fun3(void); int x; //global variable void main(){ x=10; printf("x = %d\n",x); printf("x = %d\n",fun1()); printf("x = %d\n",fun2()); printf("x = %d\n",fun3()); } fun1(void){ x = x+10; //global } fun2(void){ int x; x = 1; //local return x; } fun3(void){ x = x+10; //local }
运行输出
x = 10 x = 20 x = 1 x = 30
核心疑问
声明为返回int类型的fun1、fun3没有写显式return语句返回值,为什么printf还是能输出20、30这类符合预期的数值?
原因解释
- 首先要明确:这是典型的未定义行为(Undefined Behavior),不是C语言标准保证的合法效果,你当前看到的输出只是特定编译器、特定编译选项、特定硬件架构下的巧合,换环境结果可能完全不同,甚至程序直接崩溃。
- C语言标准明确规定:如果返回值类型不是
void的函数,在执行到函数体结束的}时没有通过return语句返回确定值,调用方尝试读取该函数返回值的行为没有任何标准约束,编译器可以生成任意逻辑的代码,不需要对结果负责。 - 你当前看到的“正确返回”是x86平台下常见编译器的实现习惯导致的:x86架构下,C函数返回
int类型值时,约定把返回值存放在EAX通用寄存器中。fun1和fun3里最后执行的操作是对全局变量x做加法赋值,这个运算的结果会临时存放在EAX寄存器里,函数结束前没有其他指令修改EAX的值,调用方按约定从EAX读返回值时,就刚好读到了修改后的全局x的数值。 - 这种巧合非常脆弱:只要你调高编译优化等级、换ARM/RISC-V等其他架构的编译器、在函数末尾加几行其他运算代码,返回值马上会变成不可预期的随机值。现在主流编译器(GCC、Clang)开启
-Wall警告选项时,会直接对“非void函数无return语句”的写法抛出警告,开启-Werror后会直接阻止编译。 - 额外说明:原示例代码存在多处不符合现代C标准的写法:一是
fun1、fun3定义时省略返回值类型,这是已经被废弃的C89隐式int规则,C99及之后的标准不再支持这种写法;二是void main()不是C标准规定的合法main函数签名,标准写法为int main(void);三是fun3内没有定义局部变量x,注释标注操作的是local变量属于笔误,实际操作的是全局变量x。
内容的提问来源于stack exchange,提问作者Israk Ahmed
相关产品推荐
相关产品推荐

