主要流程
主要流程包括:
預處理->編譯->匯編->鏈接
- 預處理:源代碼.c文件——>.i文件
處理#開頭的代碼,加載頭文件、宏替換、條件編譯等
- 編譯:.i文件——>.s文件(匯編代碼)
- 匯編:.s文件——>.o(.obj)文件(機器代碼)
- 鏈接:.o文件——>.out 可執行文件
編譯過程的作用:目標文件和可執行文件格式相同都是二進制代碼,但是只完成了編寫部分代碼的二進制轉換,執行程序還需要將目標文件和系統組件(包括標准庫和動態鏈接庫能)結合。執行的位置可以是在編譯時、程序加載時或者執行過程中。
Gcc優化
- -O0:無優化(默認)。
- -O1:使用能減少目標文件大小以及執行時間並且不會使編譯時間明顯增加的優化.在編譯大型程序的時候會顯著增加編譯時內存的使用。
- -O2: 包含-O1的優化並增加了不需要在目標文件大小和執行速度上進行折衷的優化.編譯器不執行循環展開以及函數內聯.此選項將增加編譯時間和目標文件的執行性能。(一般優化到-O2就可以了)
- -Os:專門優化目標文件大小,執行所有的不增加目標文件大小的-O2優化選項.並且執行專門減小目標文件大小的優化選項。
- -O3: 打開所有-O2的優化選項並且增加 -finline-functions, -funswitch-loops,-fpredictive-commoning, -fgcse-after-reload and -ftree-vectorize優化選項。
優化效果實例:
gcc在編譯的時候可以使用-O、-O2和-O3選項(字母O要大寫)來對代碼進行優化,以下是一個故意創建的代碼歐用於配合time命令測試該優化選項的效果,time命令的輸出為real、user和sys三項,各個部分說明如下:
real:進程總的執行時間, 它和系統負載有關(包括了進程調度,切換的時間),
user:被測量的進程中用戶指令的執行時間;
sys:被測量進程中內核代用戶指令執行的時間,user和sys的和被稱為CPU時間。
user:被測量的進程中用戶指令的執行時間;
sys:被測量進程中內核代用戶指令執行的時間,user和sys的和被稱為CPU時間。

#include <stdio.h> int main(void) { unsigned long int counter; /*定義相關的變量*/ unsigned long int result; int i; unsigned long int temp; unsigned int five; /*判斷條件在每一次for循環時都會進行一次計算*/ for (counter=0; counter < 2009 * 2009 * 100 / 4 + 2010; counter += (10 - 6) / 4) { temp=counter / 1979; for(i=0; i < 20; i++) { five=200*200/8000; /*每一次for循環都會進行復雜的計算*/ } result=counter; } printf("Result is %ld\n", result); return 0; }
輸入以下代碼查看三種不同的編譯選項對應的執行時間差異(不同的機器有不同的差別,相同的機器在同時運行不同的其他程序的時候也有差異)
alloy@raspberrypi:~/linuxcupdate/chapter4$ gcc inefficient.c -o inefficient alloy@raspberrypi:~/linuxcupdate/chapter4$ time ./inefficient alloy@raspberrypi:~/linuxcupdate/chapter4$ gcc -O2 inefficient.c -o inefficient alloy@raspberrypi:~/linuxcupdate/chapter4$ time ./inefficient alloy@raspberrypi:~/linuxcupdate/chapter4$ gcc -O3 inefficient.c -o inefficient alloy@raspberrypi:~/linuxcupdate/chapter4$ time ./inefficient