编译器中的哪个函数负责接受main()的返回值

时间:2014-10-11 02:47:22

标签: c compilation compiler-warnings

这是我从先生那里得到的一个奇怪的问题。他说如果我们不在main()之前放置返回类型,它将返回一个垃圾值。他说这个垃圾值被返回给C编译器中的一个函数。

  1. 哪个编译器功能负责?
  2. 如果此编译器函数参数是垃圾值会发生什么?
  3. e.g。 :

    main()
    {
    
     printf("Hello world");
    
    } //will return a garbage value since no return type
    

5 个答案:

答案 0 :(得分:3)

调用main()并安排使用main()返回的值退出程序的函数不一定有名称。目标文件通常具有crt0.o等名称,并负责调用main()并使用返回值调用exit()

代码main() { …; /* No return */ }在C99和C11中无效;您必须指定一个返回类型(int - 请参阅What should main() return in C and C++?)。在C89 / C90标准中,您可以在没有返回类型的情况下编写main(),但是您必须明确地从main()返回一个值,否则您确实会返回垃圾。

然而(在一些人认为是错误的,虽然它与C ++兼容),C99立法规定如果你没有显式地从int main(void) { …; /* No return */ }返回一个值,编译器会有效地插入return 0;你。

因此,显示的代码是C89 / C90(或预标准)C,应该有回报。

答案 1 :(得分:1)

我不相信这个函数的名称有任何约定,但它负责使用main()的返回值来设置O / S记录的ERROR LEVEL值。通常可以检查该值(通常在批处理文件处理中)以确定程序是否成功完成(0)与错误指示相比,对于不同的非零值可能具有意义。

答案 2 :(得分:1)

在标准C(和C ++)中,main必须具有返回类型int。如果没有返回类型,可能会返回一些随机的四个字节的内存。实际上,在许多系统(如Unix和Linux)上只使用一个字节,因为程序的返回值始终为[0,255]。如果返回垃圾值,大多数系统会将零解释为成功,将非零解释为失败,因此您的程序调用可能会显示为"失败"从外部来电者的角度来看。

另一方面,有些系统可能会容忍这种错误,因为很多遗留代码会这样做,而且只是为你返回0。

有一些"启动"通常在main()之前运行的代码。这与平台有关,但不知何故,它需要传递参数并将main的值返回给操作系统。

答案 3 :(得分:0)

如果在调用中添加-v标志,即g++ -std=c89 -x c -O2 -Wall -pedantic -pthread -v main.cpp,您会注意到gcc将一些目标文件添加到链接器,即crtbegin.o,crtend.o,crti .o和crtn.o,以及crt1.o或crt0.o(也可能是。)后者包含初始化进程并调用{{1}的入口点函数(即_start) }。

注意这实际上是依赖于实现和操作系统的(但是以linux上的gcc为例。)


在C89中,如果您没有为main指定返回值,则返回的值是未定义的。

2.1.2.2托管环境

  

从初始调用到main函数的返回相当于   使用main函数返回的值调用exit函数   作为其论点。如果main函数执行指定的返回   没有值,返回主机环境的终止状态是   未定义。

在C99中,如果没有返回类型,则无法声明函数(隐式int规则被删除。)与C89相比,C99明确指出main的返回类型:

  

应使用返回类型int定义并且不带参数:   [...]或以其他一些实施方式定义的方式。

它还删除了未定义的返回值:

5.1.2.2.3

  

1如果main函数的返回类型是兼容的类型   int,从初始调用到main函数的返回是等价的   使用main返回的值调用exit函数   作为其参数的函数; 10)到达终止的}   main函数返回值0.如果返回类型不是   与int兼容,终止状态返回给主机   环境未明确。

答案 4 :(得分:0)

  

哪个编译器功能负责?

无。该值将返回到环境中。在操作系统环境中,该值可用于确定程序执行的状态。按惯例,零是成功,非零是错误。 shell脚本或启动进程的其他程序可以使用该值 - 例如,make实用程序使用它来确定构建步骤是否失败。

当运行C程序时,它由OS加载并启动,然后链接器包含的启动代码执行诸如设置堆栈指针,初始化静态数据,初始化库,然后调用main()之类的任务。 。当main()返回时,代码可能会在操作系统卸载代码并执行自己的清理之前执行一些清理。


  

如果此编译器函数参数是垃圾值会发生什么?

非零值可能被解释为错误条件,但只是明确地检查它并以这种方式解释它 - 例如shell脚本,批处理文件或make。除了设置环境变量 ERRORLEVEL 之外,操作系统不执行任何操作,因此可以在事件发生后查询该值。