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和 我們自己寫的代碼文件鏈接的時候,就會去找缺失的符號定義。如果未找到,就會報未找到對應標識的錯誤。
@? readelf? -s? crt1.o? ?可以查看符號表,其中信息如下所示,可以看見在13行中 有一個 未被定義的全局變量main ,這個main就需要由用戶程序來提供。
Symbol table '.symtab' contains 19 entries:Num: Value Size Type Bind Vis Ndx Name0: 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_fini10: 0000000000000030 5 FUNC GLOBAL HIDDEN 3 _dl_relocate_static_pie11: 0000000000000000 47 FUNC GLOBAL DEFAULT 3 _start12: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND __libc_csu_init13: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND main14: 0000000000000000 0 NOTYPE WEAK DEFAULT 8 data_start15: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_16: 0000000000000000 4 OBJECT GLOBAL DEFAULT 5 _IO_stdin_used17: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND __libc_start_main18: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 8 __data_startC run-time library里面含有初始化代碼,如果選擇不用crt去鏈接的話,那么你crt對應的程序初始化功能也就沒有了。
總結
以上是生活随笔為你收集整理的Linux C: 为什么C都必须有一个main函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux C : GDB调试命令汇总
- 下一篇: 操作系统原理:读写者经典同步问题