核心區別
| 場景 | gcc | g++ |
| .c 文件 | 視為 C 代碼 | 視為 C++ 代碼 |
| .cpp/.cc/.cxx 文件 | 視為 C++ 代碼 | 視為 C++ 代碼 |
| 鏈接階段 | 不自動鏈接 C++ 標準庫 | 自動鏈接 libstdc++ |
| 預定義宏 | __STRICT_ANSI__ 等 C 宏 | 額外定義 __GXX_EXPERIMENTAL_CXX0X__ 等 C++ 宏 |
本質:g++ 等價於 gcc -x c++ -lstdc++ -shared-libgcc。編譯階段 g++ 內部調用 gcc(實際調用 cc1plus)。
GCC 四階段編譯流程
source.c
│ 預處理 (cpp) -E
▼
source.i
│ 編譯 (cc1/cc1plus) -S
▼
source.s
│ 匯編 (as) -c
▼
source.o
│ 鏈接 (ld) (默認)
▼
a.out (可執行文件)
階段控制參數
| 參數 | 停止階段 | 輸出 | 典型用途 |
| -E | 預處理 | .i (stdout) | 檢查宏展開、條件編譯 |
| -S | 編譯 | .s | 查看匯編優化、內聯展開 |
| -c | 匯編 | .o | 分離編譯、構建靜態庫 |
| (無) | 鏈接 | 可執行文件 | 完整構建 |
常用參數速查表
語言標準
-std=c11 -std=c++17 -std=gnu++20 # 指定標準
-ansi -pedantic # 严格 ANSI,禁用 GNU 擴展
優化等級
-O0 無優化(調試默認)
-O1 基礎優化
-O2 全優化(發布默認)
-O3 激進優化(可能增大代碼、改變浮點語義)
-Os 體積優化
-Ofast -O3 + 忽略浮點精度 + 激進循環優化
調試信息
-g 基礎調試信息
-ggdb GDB 專用豐富信息(推薦)
-g3 最大調試信息(含宏定義)
-gstabs+ STABS 格式 + GDB 擴展
頭文件搜索路徑
-I/path/include # 添加搜索路徑(雙引號/尖括號均搜)
-I- # 分隔符:前面 -I 只對雙引號有效,後面對所有有效
-isystem /path # 系統頭文件路徑(抑制警告)
-idirafter /path # 在標準路徑後搜索
宏定義/取消
-DNAME # #define NAME 1
-DNAME=VALUE # #define NAME VALUE
-UNAME # #undef NAME
鏈接控制
-lname # 鏈接 libname.a/.so
-L/path # 庫搜索路徑
-static # 靜態鏈接(不依賴 .so)
-shared # 動態鏈接(生成 .so)
-Wl,option # 傳遞給鏈接器 ld
-Wa,option # 傳遞給匯編器 as
輸出控制
-o outfile # 指定輸出文件名
-pipe # 用管道替代臨時文件(加速構建)
-save-temps # 保留 .i .s .o 中間文件
實戰構建示例
單文件編譯運行
g++ -std=c++17 -O2 -Wall -Wextra -o main main.cpp && ./main
多文件分離編譯
g++ -c -o util.o util.cpp
ar rcs libutil.a util.o
g++ -o main main.cpp -L. -lutil
構建動態庫
g++ -g -O0 -std=c++17 -o main main.cpp
常用命令
| 命令 | 縮寫 | 功能 |
| break main | b main | 在 main 處設置斷點 |
| run arg1 arg2 | r | 運行程序帶參數 |
| next | n | 單步跳過函數調用 |
| step | s | 單步進入函數 |
| print var | p var | 打印變量值 |
| display var | disp var | 每次停下自動打印 |
| backtrace | bt | 查看調用棧 |
| info locals | | 顯示局部變量 |
| continue | c | 繼續運行 |
| quit | q | 退出 GDB |
條件斷點
break foo.cpp:42 if i == 100
監視點
watch ptr->field
常見構建錯誤診斷
| 錯誤 | 原因 | 解決 |
| undefined reference to `foo' | 缺少定義或鏈接順序錯 | 檢查 .cpp 編譯、庫順序 `-lA -lB` (A 依賴 B) |
| multiple definition of `bar' | 頭文件定義非 inline 函數/變量 | 頭文件只聲明,定義放 .cpp;或加 inline |
| fatal error: xxx.h: No such file | 頭文件路徑缺失 | 添加 -I/path |
| error: ‘NULL’ was not declared | C++11+ 需 <cstddef> 或 nullptr | 包含頭文件或用 nullptr |
總結
- C++ 代碼用 g++:自動處理 C++ 標準庫鏈接、宏定義
- 理解四階段:-E/-S/-c 控制停止點,排查宏/匯編/鏈接問題
- 優化與調試互斥:-O2 發布,-g -O0 調試
- 鏈接順序敏感:依賴庫放後面,循環依賴用 `-( -lA -lB -)`
- GDB 是生產力工具:熟練掌握 bt/p/n/s/c/w 核心命令
掌握 GCC/G++ 參數,是從「會寫代碼」到「會構建項目」的關鍵一步。