簡體   English   中英

關於GCC編譯器和鏈接器的問題

[英]Questions about the GCC compiler and linker

假設您的程序由兩個源文件(main.c和auxiliary.c)和兩個頭文件(declarations.h和auxiliary.h)組成。

然后運行編譯器,如下所示:

$gcc main.c auxiliary.c -o myprogram

問題1 :編譯器是否會為我的程序創建一個單獨的目標文件(即,只缺少庫),還是會創建兩個目標文件,每個源文件一個(然后將所有內容鏈接在一起)?

問題2 :是否需要單獨調用鏈接器? 因為如果您使用上面的命令,編譯器會為您處理,對吧?

問題3 :為什么有些庫會自動鏈接(例如,stdio)以及為什么有些庫需要額外的工作(例如,math.h需要在編譯時添加-lm)。 -lm代表什么?

問題4 :假設您有一個源文件,並且您的程序不需要任何外部庫。 這是否意味着您從編譯器獲得的目標代碼已經可執行? (即編譯它像$ gcc -c main.c)。

  1. gcc通常會為每個源文件創建一個對象。 但是有一個-combine選項可以告訴你不想這樣做。

  2. 當你有幾十個源文件時重新編譯所有內容並不是一個好主意(當你有更多時,你將它們分成庫)。

  3. 歷史。 曾經有一段時間 - 在共享庫之前 - 當數學庫相對較大並將其放入每個可執行文件中時,即使那些不需要它的人也被認為是浪費的(使用數學庫涉及像printf這樣的函數的替代版本,所以即使不使用你也有成本)

  4. 我等着看一個程序,它甚至不使用標准庫的任何部分(邏輯上調用main作為exit(main(argc, argv))所以至少exit調用)然后有啟動和完成代碼。

  1. gcc為每個源文件創建一個目標文件,然后鏈接它們以構建可執行文件。

  2. 您的示例證明gcc能夠鏈接所有需要的步驟

  3. 自動鏈接的庫是標准C庫。 其他需要指定。 這允許在不需要atan2()時構建較小的可執行文件。
    -lm向編譯器指示它應該找到其id為m的數學庫。 在Unix上,它的文件名是libm.solibm.a具體取決於鏈接是動態的(在運行時執行並導致較小的可執行文件)還是靜態的(在鏈接時執行並導致獨立的可執行文件)。

  4. 不可以。無論如何,它必須與標准C庫相關聯。 而且,目標代碼的文件格式與可執行文件不同。

問題1 :使用'-save-temps'執行gcc語句,您將看到編譯器創建了兩個目標文件。

問題2 :對鏈接器的調用是隱含的。 'gcc'命令實際上不是一個編譯器,但是通過根據需要調用預處理器,編譯器,匯編器和鏈接器來驅動編譯過程。 在小程序中,讓'gcc'處理所有事情是個好主意,但對於包含許多源文件的大型程序,這意味着重新編譯所有源文件,即使它們沒有改變。

問題3 :這是一個慣例問題。 (m庫是數學庫。)

問題4 :不,事實並非如此。 總是需要鏈接一些額外的代碼來處理流程啟動/拆卸要求。 在linux上,這些是crt1.o,crti.o,crtbegin.o和crtn.o文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM