空 void main() 程序的退出代码是什么意思?

what's the meaning of exit code of program with empty void main()?

我做了一个简单的 C 程序,如下所示,main 是空的,并用 gcc 编译了它

void main(){
}

执行后,return 退出代码为 25, 如果我添加一个 printf 语句,在包含 stdio.h 之后,它 returns 退出代码 5

这里的 255 是什么意思,为什么它被 main() 之前或之后执行的任何代码 return 编辑? 如果我使用 int main() 并且不放置 return 语句,退出代码为零。

what's the meaning of 25 and 5 here

C 语言规范未定义 main() 声明为 return void 的程序的行为。尽管如此,接受此类代码的实现可能会也可能不会为其定义行为。那么,在一般意义上,no退出状态对于具有void main().

的程序具有任何意义或意义

显然,GCC 确实接受代码,但我在 GCC's documented C extensions 中找不到其行为的定义,因此在那种特定情况下,您观察到的退出状态也没有任何意义。

and why it's being returned by whatever code that is executed before or after main()?

没有特别的原因。行为未定义。

exit code is zero if I use int main() and don't put a return statement.

那个案例很明确。 C 指定如果执行到达对 main() 的初始调用的末尾(假定使用两个 C 标准签名之一声明,两者都是 return int),则行为如下如果 exit(0) 被调用。这是一个特例。如果执行到达非 void 函数的右大括号,并且其调用者对 return 值执行任何操作,则行为未定义。

(加入 John Bollinger 的回答)

* void main

旧的 ISO C 标准 (ISO/IEC 9899:1999) 声明:

[main] shall be defined

  • with a return type of int and
    • with no parameters […] or
    • with two parameters […] or equivalent; or
    • in some other implementation-defined manner.

C 标准的 § 5.1.2.2.1 ¶ 1

If the return type is not compatible with int, the termination status returned to the host environment is unspecified.

§ 5.1.2.2.3 ¶ 1

这表示允许不存在 return int 的表单是有意的。

许多编译器的手册(例如 Watcom C/C++、IBM VisualAge C/C++、Microsoft Visual C/C++)指出 main 可能具有 return 类型 void 所以带有 void main() 的程序是一个合格的程序。

很长一段时间以来,很多代码都是用 void 的 return 类型编写的。 gcc(可能)认为与遗留代码兼容很重要并允许 void main() 但在那种情况下:

  • 它给出警告 (warning: return type of ‘main’ is not ‘int’);
  • 程序的 return 值未定义。

参考文献:

* int main

int main() {}

这在 C89/90 中未定义,但在以下版本中定义明确(其中 returns 0)。

*实际值

在 x86 上,EAX 寄存器通常用于 return 值。所以

int main() {}

被编译成类似的东西:

main:
        push    rbp
        mov     rbp, rsp
        mov     eax, 0
        pop     rbp
        ret

对于

void main() {}

最简单的操作是删除 mov eax, 0:

main:
        push    rbp
        mov     rbp, rsp
        nop
        pop     rbp
        ret

如果添加 printf 语句:

#include <stdio.h>

void main()
{
  printf("1234");
}

你得到:

.LC0:
        .string "1234"
main:
        push    rbp
        mov     rbp, rsp
        mov     edi, OFFSET FLAT:.LC0
        mov     eax, 0
        call    printf
        pop     rbp
        ret

printf 调用改变了 EAX 寄存器(returns 写入流的字符数,EAX 用于 return 值)。