当前位置:  开发笔记 > 运维 > 正文

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

如何解决《为什么main()不能在C中声明为静态?》经验,为你挑选了2个好方法。

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

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

什么是外部联系?



1> Johannes Sch..:

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

external linkage意味着其他所谓的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



2> Barry Kelly..:

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

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

推荐阅读
有风吹过best
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有