Linux C: 为什么C都必须有一个main函数

gcc的编译过程分为三步:

第一步 将 *.c 文件分别通过编译器解析成汇编语言    *.s     。

第二步将  *.s 文件分别通过汇编器生产目标文件  *.o      。 

第三步将 c.o文件通过链接器合成一个  out 的可执行文件  。

当执行.out 或者 .exe  可执行文件时,程序入口通常是main 函数。一个程序中,必须要有一个入口函数来告诉链接器指明代码从哪里开始执行。大部分连接器的默认函数入口都是main函数。当然你也可以告诉链接器,入口函数是不是main函数,而是其他函数。这个函数名字只要你愿意,改什么都可以,只需要在链接的时候告诉链接器就可以。所以C程序包括其他高级语言的程序main函数并不都是必须的,只不过是链接器的默认指明的程序入口是main而已。

 如下图所示

-nostartfiles 链接的时候不使用标准系统的启动文件。

C的标准系统启动文件对应的库叫C run-time library 简称 CRT,C运行时库 ,对应的目标文件是 crt1.o  和crti.o 。 其实正真的程序入口是crt1.o中的_start 。_start中调用了一个叫main的函数。这里的符号表里会发现一个main符号是未定义的,意味者自身文件没有main这个符号,需要从其他文件来提供main。crt1.o和 我们自己写的代码文件链接的时候,就会去找缺失的符号定义。如果未找到,就会报未找到对应标识的错误。

扫描二维码关注公众号,回复: 13394621 查看本文章

@  readelf  -s  crt1.o   可以查看符号表,其中信息如下所示,可以看见在13行中 有一个 未被定义的全局变量main ,这个main就需要由用户程序来提供。



Symbol table '.symtab' contains 19 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    8 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    9 
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT   10 
     9: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_csu_fini
    10: 0000000000000030     5 FUNC    GLOBAL HIDDEN     3 _dl_relocate_static_pie
    11: 0000000000000000    47 FUNC    GLOBAL DEFAULT    3 _start
    12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_csu_init
    13: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND main
    14: 0000000000000000     0 NOTYPE  WEAK   DEFAULT    8 data_start
    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
    16: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    5 _IO_stdin_used
    17: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __libc_start_main
    18: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    8 __data_start

C run-time library里面含有初始化代码,如果选择不用crt去链接的话,那么你crt对应的程序初始化功能也就没有了。

猜你喜欢

转载自blog.csdn.net/superSmart_Dong/article/details/116891431