我們在linux中編譯c**的時候,都會使用gcc ***.c -o ***可是這一條簡簡單單的命令後隱藏著什麼呢?在輸入這條命令,敲擊回車之後有發生了什麼呢?
1,預編譯,我們在寫程式的時候一般會使用include,會使用巨集定義define,使用編譯選項。這些語句的處理都是在預編譯的時候解決的。具體來講,預編譯刪除#define,展開所有的巨集定義,預編譯處理#ifdef #endif等編譯指令,預編譯處理#include指令,會通過環境變數或者編譯指定的引數找到對用的標頭檔案的完整路徑,對include的處理使用了遞迴處理,預編譯還會刪除注釋,增加行號。但是對於#pragma命令,預編譯不做處理,因為這條指令編譯器還會用到。
可以使用gcc -e ***.c產生預編譯後的 ***.i 檔案;
2, 編譯, 編譯過程是將預處理後的檔案進行一系列的操作,最終生成彙編**的過程。這個過程時整個程式構建的核心部分。這之中包括了幾個重要的步驟,詞法分析,語法分析,中間語言生成,目標**生成與優化。需要特別宣告的是優化過程,編譯器時保守的,在優化過程中為了保證程式執行的正確性,在某些可以優化的地方編譯器卻沒有執行優化,這就要求程式設計師盡可能優化自己的**。但是即便如此,仍然存在過度優化的可能行,例如在多處理系統中,多個cpu引用同乙個變數,為了提高速度變數可能快取到暫存器中而沒有被及時寫回,這時候就有可能引發執行緒錯誤。同時在優化的過程中編譯器有可能會修改指令的執行順序,這也存在潛在的危險。
可以使用gcc -s ***.c -0 ***.s產生編譯後的檔案
3,彙編,彙編就是將組合語言程式設計機器碼的過程,彙編的過程相對簡答,每一條彙編**都對應著乙個機器碼,在彙編過程中一一對應的可以了。
可以使用as ***.s -o ***.o 或者可以使用 gcc -c ***.s -o ***.o
4,鏈結,鏈結是和編譯一樣討厭的乙個過程,其中牽扯了很多的內容。鏈結就是將多個目標檔案整合成乙個可執行檔案的過程。其中分為動態鏈結和靜態鏈結。靜態鏈結時將多個.o檔案整合到乙個可執行檔案中,這個可執行檔案不依賴任何的外部庫。動態鏈結是在程式裝載的時候中完成的,它是將可執行檔案與.so(linux)在裝載過程中進行鏈結,這樣可以使動態庫可以進行共享,節省了記憶體和硬碟的空間。關於靜態鏈結和動態鏈結會在後續的部落格中繼續說明。
原始檔在編譯器中的處理過程
預處理 1.只進行預處理操作 gcc e demo.c demo2.i 大於號的作用是把進行預處理操作後生成的.i檔案放到大於號後面的檔案裡面,稱作重定向。經過預處理之後的檔案字尾名為.i 2.預處理做的事情包括 標頭檔案展開 巨集替換 條件編譯 條件編譯在實際應用中非常多,通過條件編譯可以選擇編譯...
編譯處理過程
編譯,編譯程式讀取源程式 字元流 對之進行詞法和語法的分析,將高階語言指令轉換為功能等效的彙編 再由匯程式設計序轉換為機器語言,並且按照作業系統對可執行檔案格式的要求鏈結生成可執行程式。c源程式標頭檔案 預編譯處理 cpp 編譯程式本身 優化程式 匯程式設計序 鏈結程式 可執行檔案 1.編譯預處理 ...
gcc編譯器簡介
在linux中選擇gcc編譯器的原因是gcc執行效率高。gcc基本用法 gcc options filename 其中options為編譯選項。例子 執行指令 gcc hello.c 則對hello.c進行編譯,如果程式沒有語法錯誤,則產生可執行檔案a.out gcc預設檔名 執行可執行檔案指令 a...