为什么 main 在这里不返回0?

我只是在看书

ISO/IEC9899:201x 委员会草案ー2011年4月12日

其中我发现下5.1.2.2.3程序终止

..reaching the } that terminates the main function returns a value of 0.

它意味着如果在 main()中没有指定任何 return 语句,并且程序运行成功,那么在 main 的大括号}处将返回0。

但是在下面的代码中,我没有指定任何 return 语句,但是它不返回0

#include<stdio.h>
int sum(int a,int b)
{
return (a + b);
}


int main()
{
int a=10;
int b=5;
int ans;
ans=sum(a,b);
printf("sum is %d",ans);
}

编译

gcc test.c
./a.out
sum is 15
echo $?
9          // here it should be 0 but it shows 9 why?
5259 次浏览

该规则是在1999年版本的 C 标准中添加的,在 C90中,返回的状态是未定义的。

可以通过将 -std=c99传递给 gcc 来启用它。

值得注意的是,返回的是9,因为返回的是 printf,它只写了9个字符。

它返回 printf的返回值,即实际打印出的字符数。

函数的返回值通常存储在 CPU 的 eax 寄存器中,因此语句“ return 4;”通常编译为

mov eax, 4;
ret;

返回 x (取决于你的编译器)类似于:

mov eax, [ebp + 4];
ret;

如果不指定返回值,那么编译器仍然会输出“ ret”,但不会更改 eax 的值。因此调用方会认为之前在 eax 寄存器中留下的是返回值。对于这个示例,它通常是返回值 printf,但是不同的编译器将生成不同的机器代码,并以不同的方式使用某些寄存器。

这是一个简化的解释,不同的调用约定和目标平台将发挥重要作用,但它应该足够的信息来解释在您的示例中“幕后”发生了什么。

如果你对汇编程序有一个基本的了解,那么比较不同编译器的反汇编是值得的。您可能会发现,一些编译器正在清除 eax 寄存器,作为一种保护措施。