我正在研究一個包含多個模塊(源文件,頭文件,庫)的項目。所有這些湯中的一個文件包含我的主要功能。編譯器如何知道我的主函數在哪裏?
我的問題是:
- 編譯器如何知道哪個模塊編譯和不呢?
- 編譯器如何識別帶有main()的模塊?
我正在研究一個包含多個模塊(源文件,頭文件,庫)的項目。所有這些湯中的一個文件包含我的主要功能。編譯器如何知道我的主函數在哪裏?
我的問題是:
如何編譯器知道哪些模塊編譯並沒有?
它沒有。你告訴他哪一個你想編譯,通常是通過編譯語句存在於makefile中。
編譯器如何識別main()裏面的模塊?
總之這是一個很大的過程,this related question已經回答了。總之,在編譯帶有標準C庫的程序時,程序的入口點設置爲_start
。現在在內部提供了main()
函數。因此,在編譯時,沒有(需要)檢查main()
的存在。在鏈接時,鏈接器應該能夠找到它可以鏈接到的一個實例main()
。這樣,main()
將作爲您程序的入口點。
因此,要回答
編譯器如何知道在哪裏我的主要功能是什麼?
它確實(並且不需要)。這是鏈接器的工作,具體而言。
編譯器本身並不關心哪個文件包含哪些函數; main()
並不特別。但是,在鏈接階段,來自不同文件(和編譯單元,可能)的所有這些符號都是匹配的。鏈接器有一個隱藏的「模板」,它具有固定地址上的代碼,操作系統在運行程序時將始終調用該地址。該代碼將調用您的main
;因此,鏈接程序會在所有文件中查找main
。如果它不在那裏,你會得到一個未解決的符號錯誤,就像你使用了一個你忘記實現的函數一樣。
與任何其他功能相同適用於main
:您只能有一個執行;在鏈接在一起的兩個文件中有兩個main
,則會出現鏈接器錯誤,因爲鏈接程序無法確定要使用哪個文件。
更具體地說:當編譯器在鏈接模式下調用時,它充當引用C庫的特殊運行時代碼的驅動程序。可執行頭文件中的固定地址通常是名爲'_start'的符號地址。 – o11c
啓動該程序的彙編代碼(通常稱爲啓動代碼,由嵌入式人員調用)具體調用main()
。
編譯器文檔中包含main()
的原型。 當你編譯一個程序時,會產生一個目標文件。然後,源代碼中的目標文件與啓動運行時組件(通常稱爲crt0.o [bj])和C庫組件等鏈接。 如果main()
更改爲無法識別的簽名,則編譯單元將抱怨未解決的外部參考_main
或__main
。
閱讀關於編譯器的階段,你會得到答案。 – haccks
它沒有。 [enuf character for this comment] –
編譯器不關心main函數,並會編譯所有的編譯單元。稍後的鏈接器將鏈接這些鏈接並可能刪除未鏈接的功能。 –