歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

GCC 編譯C程序的方法及過程解析

目前 Linux 下最常用的 C 語言編譯器是 GCC ( GNU Compiler Collection ),它是 GNU 項目中符合 ANSI C 標准的編譯系統,能夠編譯用 C 、 C++ 和Object C 等語言編寫的程序。 GCC 不僅功能非常強大,結構也異常靈活。最值得稱道的一點就是它可以通過不同的前端模塊來支持各種語言,如Java 、Fortran 、 Pascal 、 Modula-3 和 Ada 等。開放、自由和靈活是 Linux 的魅力所在,而這一點在 GCC 上的體現就是程序員通過它能夠更好地控制整個編譯過程。在使用 GCC 編譯程序時,編譯過程可以被細分為四個階段:

  • 預處理( Pre-Processing )

  • 編譯( Compiling )

  • 匯編( Asse mbling )

  • 鏈接( Linking )

Linux 程序員可以根據自己的需要讓 GCC 在編譯的任何階段結束,以便檢查或使用編譯器在該階段的輸出信息,或者對最後生成的二進制文件進行控制,以便通過加入不同數量和種類的調試代碼來為今後的調試做好准備。和其它常用的編譯器一樣, GCC 也提供了靈活而強大的代碼優化功能,利用它可以生成執行效率更高的代碼。
  GCC 提供了 30 多條警告信息和三個警告級別,使用它們有助於增強程序的穩定性和可移植性。此外, GCC 還對標准的 C 和 C++ 語言進行了大量的擴展,提高程序的執行效率,有助於編譯器進行代碼優化,能夠減輕編程的工作量。

  1. C 程序的編譯過程主要分為四個階段:pre-processing,compiling,assembling,linking;

 

 

常用文件的後綴名:

 

gcc 預處理階段:主要對包含的頭文件(#include )和宏定義(#define,#ifdef ... )進行處理。可以使用“gcc -E” 讓gcc 在預處理之後停止編譯過程,生成 *.i 文件。

[root@localhost gcc]# gcc -E hello.c -o hello.i

gcc 編譯階段:gcc 首先要檢查代碼的規范性,是否有語法錯誤等。以確定代碼實際要做的工作,在檢查無誤後,gcc 把代碼翻譯成匯編語言。用戶可以使用-S選項進行查看,該選項只進

行編譯而不進行匯編,生成匯編代碼。

[root@localhost gcc]# gcc -S hello.i -o hello.s

gcc 匯編階段:生成目標代碼 *.o ;有兩種方式:使用 gcc 直接從源代碼生成目標代碼 gcc -c *.s -o *.o 以及使用匯編器從匯編代碼生成目標代碼 as *.s -o *.o

[root@localhost gcc]# gcc -c hello.s -o hello.o

[root@localhost gcc]# as hello.s -o hello.o

也可以直接使用as *.s, 將執行匯編、鏈接過程生成可執行文件a.out, 可以像上面使用-o 選項指定輸出文件的格式。

gcc 鏈接階段:生成可執行文件;可以生成的可執行文件格式有: a.out/*/,當然可能還有其它格式。

[root@localhost gcc]# gcc hello.o 生成可執行文件 a.out

[root@localhost gcc]# gcc hello.o -o hello 生成可執行文件 hello

gcc 常用編譯選項:

 

-Dmacro 定義指定的宏,使它能夠通過源碼中的 #ifdef 進行檢驗;

 

-O 、 -O2 、 -O3 將優化狀態打開,該選項不能與 -g 選項聯合使用; 
-v 啟動所有警報,打印編譯過程的信息;
-Wall 在發生警報時取消編譯操作,即將警報看作是錯誤;
-Werror 在發生警報時取消編譯操作,即把報警當作是錯誤;
-w 禁止所有的報警。

  1. gcc 鏈接庫文件的使用

在 linux 下開發軟件時,完全不使用第三方函數庫的情況是比較少見的,通常來講都需要借助一個或多個函數庫的支持才能夠完成相應的功能。從程序員的角度看,函數庫實際上就是一些頭文件( .h )和庫文件( .so 或者 .a )的集合。雖然 Linux 下的大多數函數都默認將頭文件放到/usr/include/ 目錄下,而庫文件則放到 /usr/lib/ 目錄下,但並不是所有的情況都是這樣。正因如此, GCC 在編譯時必須有自己的辦法來查找所需要的頭文件和庫文件。 GCC 采用搜索目錄的辦法來查找所需要的文件, -I 選項可以向 GCC 的頭文件搜索路徑中添加新的目錄。例如,如果在/home/justin/include/ 目錄下有編譯時所需要的頭文件,為了讓 GCC 能夠順利地找到它們,就可以使用 -I 選項:

# gcc foo.c -I /home/justin/include -o foo 
同樣,如果使用了不在標准位置的庫文件,那麼可以通過 -L 選項向 GCC 的庫文件搜索路徑中添加新的目錄。例如,如果在 /home/xiaowp/lib/ 目錄下有鏈接時所需要的庫文件 libfoo.so ,為了讓 GCC 能夠順利地找到它,可以使用下面的命令: 
# gcc foo.c -L /home/justin/lib -lfoo -o foo 
值得好好解釋一下的是 -l 選項,它指示 GCC 去連接庫文件 libfoo.so 。

Linux 下的庫文件在命名時有一個約定,那就是應該以lib 三個字母開頭,由於所有的庫文件都遵循了同樣的規范,因此在用-l 選項指定鏈接的庫文件名時可以省去lib 三個字母,也就是說GCC 在對-lfoo 進行處理時,會自動去鏈接名為libfoo.so 
Linux 下的庫文件分為兩大類分別是動態鏈接庫(通常以.so 結尾)和靜態鏈接庫(通常以.a 結尾),兩者的差別僅在程序執行時所需的代碼是在運行時動態加載的,還是在編譯時靜態加載的 。默認情況下,GCC 在鏈接時優先使用動態鏈接庫,只有當動態鏈接庫不存在時才考慮使用靜態鏈接庫,如果需要的話可以在編譯時加上-static 選項,強制使用靜態鏈接庫。例如,如果在home/justin/lib/ 目錄下有鏈接時所需要的庫文件libfoo.so 和libfoo.a ,為了讓GCC 在鏈接時只用到靜態鏈接庫,可以使用下面的命令:
# gcc foo.c -L /home/justin/lib -static -lfoo -o foo 的文件。

對於動態庫和靜態庫文件的創建方法,此處不作詳細解釋。

Linux升級GCC 4.8.1清晰簡明教程(Ubuntu 12.04 64位版為例)  http://www.linuxidc.com/Linux/2014-04/99583.htm 

Ubuntu下Vim+GCC+GDB安裝及使用 http://www.linuxidc.com/Linux/2013-01/78159.htm 

Ubuntu下兩個GCC版本切換 http://www.linuxidc.com/Linux/2012-10/72284.htm 

CentOS6.5升級手動安裝GCC4.8.2  http://www.linuxidc.com/Linux/2015-01/112595.htm 

GCC 的詳細介紹:請點這裡

Copyright © Linux教程網 All Rights Reserved