GCC編譯器常見選項解釋

一、簡介

        GCC(GNU Compiler Collection,GNU編譯器套件)是由GNU開發的編程語言譯器。GNU編譯器套件包括C、C++、 Objective-C、 Fortran、Java、Ada和Go語言前端,也包括了這些語言的庫(如libstdc++,libgcj等。)下面直奔主題介紹gcc編譯重要選項定義。
        GCC編譯具有一條完整的編譯鏈。gcc編譯特殊指令:file 指令,顯示文件的信息。ELF表示文件是linux裏可執行文件,LSB表示小端模式。

二、編譯過程

1 -Preprocessing預編譯:擴展宏MACRO

2.-Compilation編譯:從源文件到彙編語句

3.-Assembly彙編:從彙編語句到機器碼

4.-Linking鏈接:從機器碼到可執行文件

三、常見配置參數

1 -Wall和-W 警告信息

        一般在編譯程序的時候會加上-Wall,表示所有警告都檢測並輸出警告信息;
-Wall 包含了下面其他選項內容;
-Wcomment:註釋內容嵌套錯誤警告檢測問題,例如:/*noused1, …/*noused2*/ …*/;
-Wformat:使用scanf和printf等函數的格式化字符與實際變量的類型不一致警告;
-Wunused:聲明的變量未使用警告;
-Wimplicit :使用了未聲明的函數警告;使用其他文件定義變量但是未include頭文件;
-Wreturn-type:函數定義需要返回值,但是未return或者return後面未寫數據;
        隱藏警告信息,即不一定有問題只是可能存在的警告信息;屬於高階用法,一般大型項目或者OPEN代碼需要檢測。
-W , -Wconversion , -Wshadow , -Wcast-qual ,-Write-strings, -Wtraditional

2.-D 宏定義

        GCC宏定義功能;-DTEST_MACRO,下面語句解釋案例;
test.c文件

#include <stdio.h>
int main(void)
{
printf("Hello world!\r\n");
#ifdef TEST_MACRO
printf("TEST_MACRO\r\n");
#endif
return 0;
}

gcc編譯:gcc -Wall test.c -o test
這樣運行的結果:Hello world!
gcc編譯:gcc -Wall -DTEST_MACRO test.c -o test
這樣運行結果:Hello world! TEST_MACRO

gcc編譯器自帶的宏定義有很多,可以通過指令查看:gcc -dM /dev/null;
擴展,類似於在C和H文件夾中宏定義,gcc也可以定義帶參數的宏定義,

        GCC宏定義功能;-DNUM=123,下面語句解釋案例;

#include <stdio.h>
int main(void)
{
printf("Hello world!\r\n");
#ifdef TEST_MACRO
printf("NUM is =%d\r\n", NUM);
#endif
return 0;
}

gcc編譯:gcc -Wall test.c -o test
這樣運行的結果:編譯報錯,NUM未定義;
gcc編譯:gcc -Wall -NUM=123 test.c -o test
這樣運行結果:Hello world!
NUM is = 123

3.-save-temps 過程文件

        GCC編譯過程中保存過程文件,包括:.i 預處理文件,-s 彙編處理問題, -o二進制機器碼等。
例子:gcc -Wall -c -save-temps test.c
產生文件:test.i test.s test.o文件

4.-g 調試功能

        在目標文件生成的過程中添加可調試信息,類似於VS的DEBUG模式。機器碼對應的源碼位置(行號信息)合併到生成的可執行文件,在DEBUG模式下可以方便找到問題。GNU Debugger gdb是專門的調試工具,不僅能指示出問題代碼行號,還能在在線調試過程中看到每一步的信息。
        保存方式是符號表(symbol table),可執行文件運行過程中可以找到符號表的信息,輸出代碼執行的行號和其他信息。
        如果程序意外退出,文件會產生core文件,即軟件掛了後產生的遺留文件。
例子:gcc -Wall -g test.c

#include <stdio.h>
int function(int *p)
{
int y = *p;
return y;
}

int main(void)
{
int *p = 0;
return function(p);
return 0;
}

函數調用執行BUG,在function輸入參數p是一個空指針,main調用返回值有錯誤。
編譯:gcc -Wall -g test.c 編譯通過生成test文件;
執行:segmentation fault 故障,這裏沒有產生care dumped文件因爲沒有對linux系統配置每個程序允許的core dumped文件,查看默認大小指令:ulimit -c 結果是0,表示不允許程序產生core dumped文件;配置linux的core dumped文件權限,輸入:ulimit -c unlimited,表示產生core 文件不受限,可以正常使用該功能;
然後再次執行:segmentation fault (core dumped),報錯併產生了core dumped文件。
該功能產生的core dumped文件可以幫組開發人員找到程序崩潰的位置,使用方法如下例子;core.2297是產生的core文件
gdb test.out core.2297
顯示程序運行過程總崩潰的具體信息,gbd調試工具不在此介紹。

5.-o 編譯優化

常見優化方式,-oLEVEL ,DEBUG模式下建議關閉代碼優化。
-o0:表示不優化,DEBUG模式下的優化選擇;
-o1:1級
-o2:2級 ,投產前優化方式;
-os:2.5級
-o3:3級最高優化 非常自信開發人員;
執行時間在linux中可以對比,使用:time shell指令;如下,
gcc -Wall -o0 test.c -o test1
gcc -Wall -o1 test.c -o test2
對比時間:time ./test1 , time ./test2

6.-funroll-loops 循環優化

GCC針對源代碼中的循環語句進行優化,通過增加代碼量來換取CPU執行時間,如果對代碼存儲控制不敏感但是對CPU執行效率要求很高的代碼,可以使用該選項。

7.-lNAME 添加標準庫

GCC支持許多通用標準庫文件,使用-lNAME類似方式可以添加各類庫用於編譯過程。比如-lm是-libm.a庫的簡寫方式。新版本的GCC裏面自帶了-lm庫,不需要單獨鏈接。GCC支持
庫鏈接方法集:
gcc -Wall main.c /usr/lib/libm.a -o calc
等價於下面:
gcc -Wall main.c -lm -o calc

8.-v 冗長編譯

GCC編譯過程中,Verbose開關模式是關閉的,該功能主要顯示編譯過程中的詳細信息。例子:gcc -v -Wall hello.c 。在定位編譯錯誤的過程中非常有用。

9.-c 編譯不生成只可執行文件

例子:gcc -Wall -c test.c ,產生.o文件名稱與源文件相同,缺省規則。c表示comple。

10.-o 編譯生成可執行文件

例子:gcc -Wall test.o main.o -o test ,產生可執行文件,gcc使用ld鏈接工具產生可執行文件。

11.-I 、-L 缺省文件搜索路徑

GCC編譯執行路徑。C代碼包含H文件不需要指定絕對路徑,指定絕對路徑對代碼的移植比較困難,屬於問題代碼。使用編譯器的指定路徑選項,編譯過程中只需要指定搜索頭文件路徑。
gcc -I(這裏是大寫字母I):表示指定頭文件搜索路徑
gcc -L(這裏是大寫字母L):表示指定庫文件搜索路徑

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