天天看點

Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫

文章目錄

  • gcc如何完成
    • (1)預處理(進行宏替換)
    • (2)編譯(生成彙編)
    • (3)彙編(生成機器可識别代碼)
    • (4)連結(生成可執行檔案或庫檔案)
  • 重要概念:函數庫
    • gcc如何連結函數
    • 靜态庫與動态庫
    • file指令與ldd指令

gcc如何完成

格式: gcc [選項] [要編譯的檔案] [選項] [目标檔案]

(1)預處理(進行宏替換)

  • 預處理功能主要包括宏定義,檔案包含,條件編譯,去注釋等。
  • 預處理指令是以#号開頭的代碼行。
  • 執行個體:

    gcc –E hello.c –o hello.i

  • 選項

    -E

    ,該選項的作用是讓 gcc 在預處理結束後停止編譯過程。
  • 選項

    -o

    是指目标檔案,

    .i

    檔案為已經過預處理的C原始程式
Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫
Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫

(2)編譯(生成彙編)

  • 在這個階段中,gcc 首先要檢查代碼的規範性、是否有文法錯誤等,以确定代碼的實際要做的工作,在檢查無誤後,gcc 把代碼翻譯成彙編語言。
  • 使用者可以使用

    -S

    選項來進行檢視,該選項隻進行編譯而不進行彙編,生成彙編代碼。
  • 執行個體:

    gcc –S hello.i –o hello.s

Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫

(3)彙編(生成機器可識别代碼)

  • 彙編階段是把編譯階段生成的

    .s

    檔案轉成目标檔案
  • 讀者在此可使用選項

    -c

    就可看到彙編代碼已轉化為

    .o

    的二進制目标代碼了
  • 執行個體:

    gcc –c hello.s –o hello.o

Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫

由于是二進制檔案,一般的打開方式會是以會亂碼。

Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫

使用指令

od hello.o | less

即可查閱二進制檔案。

(4)連結(生成可執行檔案或庫檔案)

  • 在成功編譯之後,就進入了連結階段。
  • 執行個體:

    gcc hello.o –o hello

Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫

重要概念:函數庫

gcc如何連結函數

  • 我們的C程式中,并沒有定義

    printf

    的函數實作,且在預編譯中包含的

    stdio.h

    中也隻有該函數的聲明,而沒有定義函數的實作,那麼,是在哪裡實作

    printf

    函數的呢?
  • 最後的答案是:系統把這些函數實作都被做到名為 libc.so.6 的庫檔案中去了,在沒有特别指定時,gcc 會到系統預設的搜尋路徑 /usr/lib 下進行查找,也就是連結到 libc.so.6 庫函數中去,這樣就能實作函數printf了,而這也就是連結的作用

靜态庫與動态庫

  • 靜态庫是指編譯連結時,把庫檔案的代碼全部加入到可執行檔案中,是以生成的檔案比較大,但在運作時也就不再需要庫檔案了。其字尾名為

    .a

    。輸入

    gcc hello.c -o hello -static

    ,采用靜态連結
  • 動态庫在編譯連結時并沒有把庫檔案的代碼加入到可執行檔案中,而是在程式運作時由運作時連結檔案加載庫,這樣做可以節省系統開銷。動态庫字尾名一般為

    .so,gcc

    在編譯時預設使用動态庫,完成連結之後,就生成了可執行檔案。

動态連結形成的程式體積較小,比較節省資源,但是一旦庫丢失,程式就不可以運作了;而靜态形成的程式的體積很大,但具有獨立性,即便庫丢失,也不影響程式運作。

file指令與ldd指令

file

是一個檢視檔案類型的指令,如下:

Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫

我們可以看到這個檔案是一個elf形式的可執行程式,64位,平台為x86,與本部落格契合的是它是一個動态連結,那麼所對應的就是利用了動态庫。

ldd

是可以檢視一個可執行程式所依賴的庫是靜态庫還是動态庫。

Linux作業系統:gcc編譯器使用詳解gcc如何完成重要概念:函數庫

主要關注這一行,即libc.so.6 => /lib64/libc.so.6

一般來說,我們庫的字首lib以及字尾.so.6(.a)删除這些,餘下的即為語言類型,很顯然,這裡所用的是c語言的庫函數。

繼續閱讀