首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言程式編譯全過程:從源碼到可執行檔

     編輯:關於C語言

GCC 編譯四大階段詳解

以 hello.c 為例:

#include 
int main() {
    printf("Hello, world.\n");
    return 0;
}

命令 gcc hello.c 實際經歷四個階段:

1. 預處理

命令:gcc -E hello.c -o hello.i 或 cpp hello.c > hello.i

處理內容:

  • 展開所有 #define 宏
  • 處理條件編譯 #if #ifdef #elif #else #endif
  • 展開 #include 引入的檔案
  • 移除註解 // /* */
  • 添加行號與檔案標識(供除錯用)
  • 保留 #pragma 編譯器指令

2. 編譯

命令:gcc -S hello.i -o hello.s 或直接呼叫 cc1

將預處理後的 C 代碼經詞法分析、語法分析、語義分析、優化,生成組合語言代碼。現代 GCC 將預處理與編譯合併為 cc1 內部完成。

生成的 hello.s 片段:

.file "hello.c"
.section .rodata
.LC0:
.string "Hello, world."
.text
.globl main
.type main, @function
main:
    pushl %ebp
    movl %esp, %ebp
    andl $-16, %esp
    subl $16, %esp
    movl $.LC0, (%esp)
    call puts
    movl $0, %eax
    leave
    ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits

3. 匯編

命令:gcc -c hello.c -o hello.o 或 as hello.s -o hello.o

將組合語言一對一翻譯為機器指令,生成目標檔(二進位,含機器碼、符號表、重定位表)。

4. 連結

命令:gcc hello.o -o hello 或 ld ...

將目標檔與庫檔(libc、crt1.o 等)合併,解析符號引用,固定位址,生成最終可執行檔。

實戰經驗:避免未定義/重定義錯誤

近期編譯 DM8168 ARM 端程式頻遇符號錯誤,源碼檔案多、包含關係複雜。總結規律:

  1. 公共資料結構、函數宣告 集中於單一標頭檔,其他源檔 #include 該檔
  2. 跨檔案變數共享:定義處不加 extern,使用處加 extern 宣告,避免多重定義
  3. 靜態限制作用域:檔案內部函數/變數加 static,減少全域符號汙染

良好的代碼風格與模組化設計,是大型專案編譯順利的基石。

工具鏈認知

gcc 實為驅動程式,根據參數調度:

  • cc1:C 編譯器(含預處理)
  • as:匯編器
  • ld:連結器

理解各階段產物(.i, .s, .o, 執行檔)與對應工具,有助於診斷編譯錯誤、優化構建流程、進行交叉編譯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved