Linux編程簡介——gcc


在Linux環境下,我們通常用gcc將C代碼編譯成可執行文件,如下就是一個簡單的例子:

代碼文件:hello.c

    #include <stdlib.h>
    #include <stdio.h>

    void main(void)
    {
        printf("hello world!\r\n");
    }

可以通過如下指令來編譯出一個可執行文件:

    gcc hello.c

執行完該命令后,就會得到一個a.out的可執行文件。

編譯的過程

前面的例子只是簡單的介紹了一下gcc的使用方法,熟悉c編程的朋友就會知道,該步驟其實包含了預處理-->編譯-->匯編-->鏈接四步,這四步分別實現的功能如下:

  1. 預處理階段:主要處理源文件中的#ifdef、 #include和#define命令,展開宏、讀取定義的符號等。
  2. 編譯階段:檢查代碼的規范性,把代碼翻譯成匯編語言
  3. 匯編階段:是把編譯階段生成的".s"文件轉成二進制目標代碼
  4. 鏈接階段:將匯編階段生成的機器碼匯集成一個可執行的二進制代碼文件

由此可以看出,每一個階段的輸出其實就是下一個階段的輸入,用gcc是可以單獨執行這四步的:

    gcc -E hello.c -o hello.i
    gcc -S hello.i -o hello.s
    gcc -c hello.s -o hello.o
    gcc hello.o -o hello.exe

實際上,由於這四個步驟太過於復雜,往往可以像我上面那樣全部集中到一個命令中來執行:

    gcc hello.c -o hello.exe

這里我加了一個-o參數來指定輸出名稱,而不是默認的a.out。

如果有多個文件,則可以通過如下方式全部集中起來。

    gcc -o test first.c second.c third.c

這個全生成的方式雖然非常簡單,但是存在的一個問題就是:當項目較大時,如果只改了一個文件,仍需要重新編譯索引文件。

為了解決這個問題,我們往往把這個編譯過程拆分成兩步:

  1. 將各個.c文件分別編譯成.o文件
  2. 將所有.o文件鏈接成執行文件

    gcc –c first.c
    gcc –c second.c
    gcc –c third.c
    gcc -o test first.o second.o third.o

這樣,當third.c文件發生改變時,只需要重新編譯third.c和鏈接即可,這樣就省去了未變化文件的編譯時間,也就是我們通常所說的增量編譯。

    gcc –c third.c
    gcc -o test first.o second.o third.o

從上面的使用方法中我們也可以看到:

  • 當使用-c參數時,若輸入文件時.c則會同時執行執行了預處理、編譯、匯編三個階段,直接生成.o文件。
  • 輸入文件為.o時,可以直接執行鏈接操作

由於程序員往往並不關心前面兩個幾個階段生成的輸出文件,通常我們也把預處理、編譯、匯編三個階段合並在一起,統稱為編譯,輸入.c,生成.o。

常用參數:

前面其實已經演示過-E、–S、–c、–o等幾個參數的用法,其中-E及-S很少會用到,-c用於編譯生成.o文件,-o用於指定輸出文件名稱。除了這幾個生成控制的參數外,還有許多參數設置,這里主要介紹一下幾個常用的:

包含頭文件和庫:

  • -Idir: 指定編譯查找頭文件的目錄,常用於查找第三方的庫的頭文件,例:gcc test.c –I../inc -o test。
  • -Ldir : 指定鏈接時查找lib的目錄,常用於查找第三方庫。
  • -llibrary :    指定額外鏈接的lib庫

宏定義:

  • -DMACRO                         以字符串"1"(默認值)定義 MACRO 宏。
  • -DMACRO=DEFN              以字符串"DEFN"定義MACRO 宏,注意中間不能有空格。
  • -UMACRO                         取消對 MACRO 宏的定義。

調試和可執行文件形式:

  • -g 指示編譯器,在編譯的時產生調試信息。
  • -ggdb 盡可能的生成gdb的可以使用的調試信息(比-g生成的信息更多些)。
  • -static 禁止使用動態庫,編譯得到的程序會比較大,但可以自由運行。
  • -share 盡量使用動態庫,所以生成文件比較小,但是需要系統由動態庫。

告警選項:

  • -Wall   產生盡可能多的警告信息,建議始終帶上
  • -Werror  將所有的警告當成錯誤進行處理

gcc和g++

除了gcc編譯器外,還有另外一個編譯器g++,很多人往往搞不清楚這兩個編譯器的區別,很多人望文生義的認為gcc只能編c代碼,g++只能編c++代碼。實際上這兩個編譯器的主要區別如下:

  • 后綴為.c的,gcc把它當作是C程序,而g++當作是c++程序來編譯
  • 鏈接的時候gcc不會默認加上-lstdc++選項(g++會),而我們往往又沒有手動加這個選項的習慣,則導致gcc編c++代碼時,用到了stl庫時會出現鏈接失敗。

關於它們的區別的更多信息,可以參考這個文章:http://ldzyz007.iteye.com/blog/865080

為了使用簡單,可以制定如下規則:對c項目使用gcc,對c++項目使用g++。估計當時設計這個名字的意圖也是如此吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM