天天看點

程式的實作過程(編譯、連結、執行)

在ANSI C的任何一種實作中,存在兩個不同的環境

  • 第1種是翻譯環境,在這個環境中源代碼被轉換為可執行的機器指令。
  • 第2種是執行環境,它用于實際執行代碼。

标準明确說明:這兩種環境不必位于同一台機器上。

例如,交叉編譯器就是在同一台機器上運作,但它所産生的可執行代碼運作于不同類型的機器上。作業系統也是這樣。

在翻譯階段,程式實作過程如下圖:

程式的實作過程(編譯、連結、執行)

翻譯階段的兩個步驟:

  1. 組成一個程式的每個源檔案(source code)通過編譯過程分别轉換成目标代碼(object code)。
  2. 每個目标檔案由
  3. 連結器(linker)捆綁在一起,形成一個單一而完整的可執行程式(executable)。

注:連結器同時也會引入标準C函數庫中任何被該程式所用到的函數,并且它可以搜尋程式員個人的程式庫,将其需要的函數也連結到程式中。

而編譯本身也分為三個階段組成:

  1. 預處理器(preprocessor)處理--預編譯。 在這個階段,預處理器在源代碼上執行一些文本操作。
  1. 源代碼經過解析,判斷它的語句的意思。這個階段産生絕大多數的錯誤和警告。
  2. 形成符号表,産生目标代碼。

下面截圖表示程式在翻譯階段的具體功能:

程式的實作過程(編譯、連結、執行)

注: ①檔案字尾名*.i、*.s、*.o在類unix系統中,可通過gcc相關指令生成對應檔案。

②符号表:在計算機科學中,符号表是一種用于語言翻譯器(例如編譯器和解釋器)中的資料結構。在符号表中,程式源代碼中的每個辨別符都和它的聲明或使用資訊綁定在一起,比如其資料類型、作用域以及記憶體位址。符号表在編譯程式工作的過程中需要不斷收集、記錄和使用源程式中一些文法符号的類型和特征等相關資訊。這些資訊一般以表格形式存儲于系統中。如常數表、變量名表、數組名表、過程名表、标号表等等,統稱為符号表。

程式執行的過程:

  1. 程式必須載入記憶體中(由馮曼依諾計算機體系決定)。在有作業系統的環境中:一般這個由作業系統完成。在獨立的環境中,程式的載入必須由手工安排,也可能是通過可執行代碼置入隻讀記憶體來完成。
  2.  程式的執行便開始。接着便調用main函數。
  3. 開始執行程式代碼。這個時候程式将使用一個運作時堆棧(stack),存儲函數的局部變量和傳回位址。程式同時也可以使用靜态(static)記憶體,存儲于靜态記憶體中的變量在程式的整個執行過程一直保留他們的值。
  4. 終止程式。正常終止main函數;也有可能是意外終止。

運作時和編譯時的本質:

  • 像标志符(類型名、變量名、函數名等)、類型定義、const關鍵字、通路限定符(public/private/protected)、引用(&)等隻是存在于源碼中,他們不會被帶入二進制可執行程式中,這是“編譯時”的本質。
  • 存在于二進制可執行程式中的隻是指令、位址和資料,沒有别的東西(實際上位址也是資料的一種),這就是“運作時”的本質。
  • C/C++源代碼中的語句、指針和變量都将被轉化成二進制程式中的指令、位址和資料。是以,通過名字直接引用一個變量、對象即其成員,這樣的代碼在編譯和連結完成後,實際上都被轉換成了通過變量、對象或成員變量的位址(即記憶體元的位址)進行通路。

繼續閱讀