为什么main()不能在C中声明为静态?

为什么main必须被声明为具有外部链接?

为什么它不应该是静态的?

什么是外部联系?

因为您将启动文件链接到您的程序,该程序包含(通常)调用main的汇编程序代码。 如果main是静态的,那么该代码将无法调用main。

external linkage意味着其他所谓的translation-units可以在自己的翻译translation-units中看到您的符号被声明为extern。 所以,你的主要是extern,它的翻译单元符号表中会有一个条目表明它的地址。 其他翻译单元将能够在他们想要呼叫主要时跳转到该地址。

static linkage意味着您的符号是严格的翻译单位本地。 这意味着其他translation units将无法看到该符号。 因此,具有静态链接的符号可以多次出现在不同的翻译单元中,并且它们不会彼此冲突,因为它们是本地的。

编辑 :通常,编译器从翻译单元生成的文件特定于该特定编译器。 对于linux上的gcc,通常使用ELF对象格式。 您可以使用readelf -sW .o查看其符号表(下面的简单测试文件):

test.c的

 void bar(void); static int foo(void) { return 1; } int main(void) { bar(); return foo(); } 

这是readelf的输出:

 Symbol table '.symtab' contains 10 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS test.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 10 FUNC LOCAL DEFAULT 1 foo 6: 00000000 0 SECTION LOCAL DEFAULT 6 7: 00000000 0 SECTION LOCAL DEFAULT 5 8: 0000000a 36 FUNC GLOBAL DEFAULT 1 main 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND bar 

您可以看到main函数和main调用的静态foo函数。 还有一个函数被调用,该函数未在文件中定义,但在另一个目标文件中定义。 由于目标文件尚未最终链接,因此这些函数尚未分配最终地址。 在最终链接之后,这些将被安排到可执行文件中并将分配地址。 目标文件具有用于调用尚未定义的函数的条目,因此在链接文件时,这些调用指令可以存储最终地址( readelf -r .o ):

 Relocation section '.rel.text' at offset 0x308 contains 1 entries: Offset Info Type Sym.Value Sym. Name 0000001c 00000902 R_386_PC32 00000000 bar 

代码的真正起点隐藏在C运行时库中。 此运行时库调用main()例程。 为了让链接器将C RTL调用与main()函数连接,它需要在文件外部可见。

外部链接就是这样:它意味着有问题的名称作为目标文件导出的一部分可见。 链接器的工作是连接所有导入和导出,以便没有未完成的导入。