Chapter2 C與C++——2.3 編譯原理

2.3 編譯原理

很多人誤以爲編譯是一個過程,實際上,編譯一個 C/C++ 程序分爲編譯和鏈接兩個過程。

2.3.1 編譯與連接

編譯型語言的源碼是不能被直接執行的,只有滿足特定處理器架構要求的機器碼才能被 CPU 執行。將程序源碼轉變成機器碼的過程稱爲編譯,這個過程會生成擴展名爲“.o”的目標文件。

通常,一個編譯後的程序仍然是不能獨立執行的,人們還引入了靜態鏈接庫、動態鏈接庫、共享庫等,程序需要依賴於這些庫才能運行。更多的時候則是依賴於,來自於同一項目的其他源碼文件所對應的目標文件。

  • 程序A
    • 目標文件1.o <- 源碼1.cpp
    • 目標文件2.o <- 源碼2.c
    • B.dll
    • C.dll
    • D.dll

一旦程序編譯分爲了兩個步驟,我們就要區分在編譯和鏈接過程中產生的問題,如果能定位到編譯錯誤或者鏈接錯誤,將幫助我們縮小問題的範圍。例如:在編譯過程中,找不到某個符號的定義,那麼很有可能是忘記了引用相關的頭文件,或是忘記了聲明;而如果是在鏈接過程中找不到某符號,則有可能是忘記告訴編譯器要鏈接哪些額外的庫了。

2.3.2 鏈接庫

本文不打算更深入的講解編譯和鏈接的原理,但是靜態庫、動態庫、共享庫等內容確實值得進行一些介紹。

庫程序的存在是有特殊意義的。首先,庫程序極大的簡化了開發程序的複雜度——你可以直接使用某些已經實現的功能,而不必親自去編寫它;其實,那些廣泛使用的庫程序,他們通常經過了嚴格的測試,和大量的驗證,某些 bug 早已被髮掘並修復,因此,庫程序要比自己編寫的相同功能的程序更穩定可靠;最後,庫程序極大的減少了系統中程序的重複率,哪些經常要被很多程序使用到的功能,被封裝到一個共享庫中,這減少了程序所佔的存儲空間。

2.3.3 靜態庫、共享庫和動態庫

庫可以有三種使用的形式:靜態、共享和動態。

靜態庫的代碼在編譯和鏈接時就已複製到程序中,其執行不依賴於庫文件的存在,執行效率高,但是生成的程序體積大;

共享庫並沒有被編譯和鏈接到程序中,而是在程序運行時才載入,在編譯時,只是簡單地指定需要使用的庫函數,程序的運行依賴於共享庫,但其生成的程序體積相對較小;

動態庫是共享庫的另一種變化形式。動態庫同樣在程序運行時載入,但與共享庫不同的是,庫函數不是在程序運行開始就加載,而是在程序中的語句需要使用該函數時才載入,在程序執行完庫函數後釋放動態庫,騰出內存空間供其它程序使用。動態庫不僅優化了程序的存儲空間,也優化了程序運行時所需的內存空間,但是其執行效率沒有靜態庫高,並且程序的執行同樣依賴於庫文件。

練習

將個位數的加減乘除運算編寫成動態庫,每個庫函數的輸入是類似於"3+9=“這樣的字符串。在另一個程序中調用這些庫函數,記錄並判斷用戶輸入的合法性,將用戶輸入傳遞給庫函數,得到庫函數返回的結果後,調用輸出程序將結果打印出來。

在進行上題過程中,如果沒有 include 庫對應的頭文件或鏈接對應的庫文件會報什麼樣的錯誤?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章