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

Jee*_*tel 116 c linux program-entry-point return

我只是在读书

ISO/IEC 9899:201x委员会草案 - 2011年4月12日

我在5.1.2.2.3程序终止下找到了

..reaching the } that terminates the main function returns a value of 0. 
Run Code Online (Sandbox Code Playgroud)

这意味着如果你没有指定任何return语句main(),并且如果程序成功运行,那么在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);
}
Run Code Online (Sandbox Code Playgroud)

gcc test.c  
./a.out
sum is 15
echo $?
9          // here it should be 0 but it shows 9 why?
Run Code Online (Sandbox Code Playgroud)

cni*_*tar 140

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

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

作为旁注,有趣的是9返回,因为它的返回printf只写了9个字符.

  • 或者你可以在结束`}之前添加`return 0;`.它是无害的,使您的程序可以移植到较旧的编译器. (40认同)
  • 是的,x86 API通常通过`eax`寄存器返回类似值的整数.有关更多信息,请参见http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl. (8认同)
  • @ Mr.32:好观察,printf()返回字符串的长度,因此它是9,这是主要的"返回"(不使用-std = c99). (2认同)
  • 有几次我见过像"int foo(void){bar();}"这样的代码,其中"return bar()"就是这样的.尽管存在明显的错误,但此代码在大多数处理器上运行良好. (2认同)

Sum*_*Tea 15

它返回的返回值printf是实际打印出的字符数.


nog*_*182 6

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

mov eax, 4;
ret;
Run Code Online (Sandbox Code Playgroud)

并返回x(取决于您的编译器)将是这样的:

mov eax, [ebp + 4];
ret;
Run Code Online (Sandbox Code Playgroud)

如果你没有指定返回值,那么编译器仍然会吐出"ret"但不会改变eax的值.因此调用者会认为之前留在eax寄存器中的是返回值.对于此示例,它通常是返回值printf,但不同的编译器将生成不同的机器代码并以不同方式使用某些寄存器.

这是一个简化的解释,不同的调用约定和目标平台将发挥至关重要的作用,但它应该足以解释您的示例中"幕后"发生的事情.

如果您对汇编程序有基本的了解,那么有必要比较不同编译器的反汇编.您可能会发现某些编译器正在清除eax寄存器作为安全措施.

  • 编译器_might_这样做.这是未定义的.它可能会选择用打印机墨盒拍摄你的头部. (11认同)
  • @LightnessRacesinOrbit对不起,我不太关注.我想我真正想说的是,我认为在这个答案中提供的诸如noggin182等引擎盖的见解对调试非常有用.当您的程序产生意外结果时,很多时候您不知道它们来自哪里,甚至不知道代码的位置,并且了解实现细节可以指向正确的方向. (2认同)