c++文件從編譯到執行

基本步驟

預處理 -> 編譯 -> 彙編 -> 鏈接

預編譯:將源文件hello.c和相關的頭文件被預編譯器編譯成一個hello.ii文件(c語言的話.c文件預編譯成.i文件)

  • 將#define 刪除,展開所有的宏定義
  • 處理條件預編譯指令,把包含的文件插入到預編譯指令的位置(遞歸的過程)
  • 刪除註釋
  • 添加行號,文件名標示
  • 保留#progma編譯器指令

編譯:把預處理完的文件進行一系列的詞法分析、語法分析以及優化後生成相應的彙編代碼文件。

彙編:彙編器將彙編代碼轉爲機器可以執行的指令。每個彙編語句都對應一個機器指令。其實就是將.c文件轉換爲.o目標文件。

鏈接:得到.out文件。用符號來實現。當一個程序很複雜的時候,我們把每個源代碼模塊獨立的編譯,然後按照要求進行“組裝”,這個組裝的過程就是鏈接。

編譯器

將高級語言翻譯成機器語言的工具。

步驟
掃描-> 語法分析 -> 語義分析 -> 源代碼優化 -> 代碼生成 -> 目標文件優化

鏈接

定義:當一個程序很複雜的時候,我們把每個源代碼模塊獨立的編譯,然後按照要求進行“組裝”,這個組裝的過程就是鏈接。

主要內容:將每個模塊之間相互引用的部分都處理好,使得各個模塊之間能夠正確的銜接。

包括: 地址和空間分配、 符號決議、 重定位

例子: 在一個程序模塊main.c中要用到另一個模塊fun.c的foo()函數,那麼在main.c每個用到fun()函數的時候都要知道這個函數的地址。但是因爲每個程序都是單獨編譯的,編譯器並不知道foo()的地址,所以編譯器暫時用一些符號來替代,暫時將它擱置,等到鏈接時,再將這些指令的地址修正。使用鏈接器,可以直接引用其他模塊的函數和全局變量,而不需要知道他們的地址。

靜態鏈接與動態鏈接

靜態鏈接

就是在編譯鏈接時直接將需要的執行代碼拷貝到調用處,優點就是在程序發佈的時候就不需要的依賴庫,也就是不再需要帶着庫一塊發佈,程序可以獨立執行,但是體積可能會相對大一些。
優點
代碼裝載速度快,執行速度比動態鏈接快
只需要保證開發者的計算機有正確的lib文件
缺點
生成可執行文件較大,可能包含相同的代碼拷貝

動態鏈接:

就是在編譯的時候不直接拷貝可執行代碼,而是通過記錄一系列符號和參數,在程序運行或加載時將這些信息傳遞給操作系統,操作系統負責將需要的動態庫加載到內存中,然後程序在運行到指定的代碼時,去共享執行內存中已經加載的動態庫可執行代碼,最終達到運行時連接的目的。優點是多個程序可以共享同一段代碼,而不需要在磁盤上存儲多個拷貝,缺點是由於是運行時加載,可能會影響程序的前期執行性能。

優點
節省內存並減少頁面交換
dll文件與exe文件獨立,只需要保證接口不變,更換dll文件對exe無影響,極大地提高可維護性和可拓展性
不同的編譯語言可以用同一個dll文件
適用於大規模的軟件開發,是的開發過程獨立,耦合度小,便於不同開發者和開發組織者之間進行開發和測試。
缺點
如果程序依賴的dll文件不存在,載入動態鏈接時,程序會終止並給出錯誤提示,運行時動態鏈接程序會加載失敗
速度慢

區別

  1. 多次調用一個外部的函數(dll文件orlib文件),靜態鏈接可能會有多份拷貝,動態鏈接只有一份拷貝
  2. 靜態鏈接的話lib文件中的指令會被包含到exe執行文件中,動態鏈接的話dll文件不必包含在exe執行文件中,exe可以隨時動態的卸載和引用這個dll文件。
  3. 靜態鏈接庫不能再包含其他動態鏈接庫和靜態庫,而在動態鏈接庫中可以再包含其他動態鏈接庫和靜態庫。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章