我只是在阅读
ISO/IEC 9899: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?
gcc
本身(对于 4.6.2 版)编译的语言非常相似,但不太像 C。它编译 GnuC89——一种“松散地”基于 C89 的语言。
sum()
中的 return
语句上的括号是不必要的。 int main()
应该是 int main(void)
。
该规则是在 1999 版的 C 标准中添加的。在 C90 中,返回的状态是未定义的。
您可以通过将 -std=c99
传递给 gcc 来启用它。
附带说明一下,有趣的是,返回了 9,因为它是 printf
的返回,它只写了 9 个字符。
它返回 printf
的返回值,这是实际打印出来的字符数。
%errorlevel%
,但在 linux 中退出代码和 main
的返回值有什么区别?
printf
的 返回值,在这种情况下是 9,然后在使用某些 gcc 版本时以某种方式“提升”为 main
的退出代码。
函数的返回值通常存储在 cpu 的 eax 寄存器中,因此语句“return 4;”通常会编译为
mov eax, 4;
ret;
并返回 x (取决于您的编译器)将类似于:
mov eax, [ebp + 4];
ret;
如果你没有指定返回值,那么编译器仍然会吐出“ret”,但不会改变 eax 的值。所以调用者会认为之前留在 eax 寄存器中的是返回值。对于这个例子,它通常是返回值 printf,但不同的编译器会生成不同的机器代码并以不同的方式使用一些寄存器。
这是一个简化的解释,不同的调用约定和目标平台将发挥至关重要的作用,但它应该足以解释您的示例中“幕后”发生的事情。
如果您对汇编器有基本的了解,则值得比较不同编译器的反汇编。您可能会发现一些编译器正在清除 eax 寄存器作为保护措施。
}
之前添加return 0;
。它是无害的,并使您的程序可移植到较旧的编译器。eax
特别是在 x86 .eax
寄存器返回类似整数的值。有关详细信息,请参阅 en.wikipedia.org/wiki/X86_calling_conventions#cdecl。