c語言的編譯與調試
1. GCC/G++
gcc和g++是GNU Compiler Collection中的編譯器,分別用于編譯C和C++程序。它們的編譯過程主要包括四個步驟:預處理(Pre-Processing)、編譯(Compiling)、匯編(Assembling)、鏈接(Linking)。
1.1 編譯過程
-
預處理(Pre-Processing):
gcc -E hello.c -o hello.i對
hello.c文件進行預處理,生成預處理文件hello.i。作用:擴展宏、包含頭文件、處理條件編譯、刪除注釋等。
-
編譯(Compiling):
gcc -S hello.i -o hello.s對預處理文件進行編譯,生成匯編文件
hello.s。作用:將高級語言代碼轉換為匯編語言,便于進一步轉換為機器代碼。
-
匯編(Assembling):
gcc -c hello.s -o hello.o對匯編文件進行匯編,生成目標文件
hello.o。作用:將匯編代碼轉換為機器代碼,包含程序的二進制指令,但還未鏈接庫函數或其他目標文件。
-
鏈接(Linking):
gcc hello.o -o hello對目標文件進行鏈接,生成可執行文件
hello。作用:生成最終的可執行程序,可以在目標操作系統上運行。
可以一步完成所有過程:
gcc hello.c -o hello
或者只生成目標文件:
gcc -c hello.c -o hello.o
1.2 GCC基本使用
-
編譯單個C文件并生成可執行文件:
gcc -o outputfile sourcefile.c-o outputfile:指定輸出的可執行文件名。sourcefile.c:要編譯的源文件。 -
編譯多個C文件并生成可執行文件:
gcc -o myprogram file1.c file2.c file3.c -
編譯并生成目標文件(.o文件):
gcc -c file.c-c:僅編譯,生成目標文件(object file)。 -
指定頭文件目錄:
gcc -Iinclude -o myprogram src/file1.c src/file2.c-Iinclude:指定包含頭文件的目錄include。詳細解釋:
-I選項用于指定頭文件的搜索目錄。這在包含自定義頭文件或者頭文件不在標準目錄時非常有用。頭文件(
.h或.hpp文件)通常包含函數聲明、宏定義、數據類型、預處理指令等。當編寫一個程序時,頭文件可以被多個源文件包含,以便共享這些聲明和定義。編譯器默認會在一些標準目錄中搜索頭文件,比如
/usr/include和/usr/local/include。如果頭文件不在這些默認目錄中,編譯器就無法找到它們,會報錯。使用
-I選項可以告訴編譯器在指定目錄中搜索頭文件。假設你的頭文件在一個自定義目錄中,比如include目錄,可以使用以下命令:gcc -Iinclude -o myprogram src/main.c這樣編譯器就會在
include目錄中找到頭文件。以下是一個示例:// include/myheader.h #ifndef MYHEADER_H #define MYHEADER_H void myFunction(); #endif // src/main.c #include "myheader.h" #include <stdio.h> void myFunction() { printf("Hello from myFunction!\n"); } int main() { myFunction(); return 0; }編譯命令:
gcc -Iinclude -o myprogram src/main.c -
鏈接目標文件生成可執行文件:
gcc -o myprogram file1.o file2.o
1.3 GCC常用選項
-
編譯優化:
-O1、-O2、-O3:不同級別的優化。-Os:優化生成的代碼大小。 -
調試信息:
-g:生成調試信息,用于調試程序。 -
警告信息:
-Wall:啟用所有常見的警告。-Werror:將所有警告視為錯誤。
1.4 G++使用
g++用于編譯C++程序,使用方法與gcc類似:
-
編譯單個C++文件并生成可執行文件:
g++ -o outputfile sourcefile.cpp -
編譯多個C++文件并生成可執行文件:
g++ -o myprogram file1.cpp file2.cpp -
編譯并生成目標文件(.o文件):
g++ -c file.cpp-c:僅編譯,生成目標文件(object file)。 -
指定頭文件目錄:
g++ -Iinclude -o myprogram src/file1.cpp src/file2.cpp-Iinclude:指定包含頭文件的目錄include。 -
鏈接目標文件生成可執行文件:
g++ -o myprogram file1.o file2.o
2.Makefile
Makefile 是用于自動化編譯和構建軟件項目的工具。在大型項目中,手動編譯每個文件非常繁瑣,使用 Makefile 可以簡化這一過程。Makefile 由一系列規則(rules)組成,每個規則包含目標(target)、依賴(dependencies)和命令(commands)。
2.1 基本結構
一個基本的 Makefile 的規則結構如下:
target: dependencies
command
- target:要生成的文件或目標,可以是可執行文件、目標文件或其他規則。
- dependencies:生成目標所依賴的文件或其他目標。
- command:生成目標所需執行的命令。
2.2 示例
假設有以下項目結構:
project/
├── include/
│ └── myheader.h
├── src/
│ ├── main.c
│ ├── file1.c
│ ├── file2.c
├── Makefile
Makefile 內容如下:
# 指定編譯器
CC = gcc
# 編譯選項
CFLAGS = -Wall -g -Iinclude
# 源文件目錄
SRC_DIR = src
# 所有的源文件
SRCS = $(wildcard $(SRC_DIR)/*.c)
# 生成的目標文件
OBJS = $(SRCS:.c=.o)
# 生成的可執行文件名
TARGET = myprogram
# 默認規則,生成最終的可執行文件
all: $(TARGET)
# 生成最終的可執行文件 $(TARGET),依賴所有目標文件 $(OBJS)
$(TARGET): $(OBJS)
$(CC) -o $@ $^
# 生成目標文件的規則
$(SRC_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理規則
clean:
rm -f $(OBJS) $(TARGET)
# 打印文件列表
print:
@echo "Source files: $(SRCS)"
@echo "Object files: $(OBJS)"
# 偽目標
.PHONY: all clean print
2.3 變量
- CC:指定編譯器,通常為
gcc或g++。 - CFLAGS:編譯選項,如包含目錄(
-I)、警告(-Wall)、調試信息(-g)等。 - SRCS:源文件列表,由
wildcard函數生成。 - OBJS:目標文件列表,由源文件列表通過模式替換生成。
- TARGET:最終生成的可執行文件名。
2.4 規則說明
-
all 規則:
all: $(TARGET)默認規則,生成目標文件
$(TARGET)。 -
$(TARGET) 規則:
$(TARGET): $(OBJS) $(CC) -o $@ $^生成最終的可執行文件
$(TARGET),依賴所有目標文件$(OBJS)。 -
模式規則:
$(SRC_DIR)/%.o: $(SRC_DIR)/%.c $(CC) $(CFLAGS) -c $< -o $@通用規則,將
.c文件編譯為.o文件。$<代表第一個依賴文件(即源文件),$@代表目標文件(即目標文件)。 -
clean 規則:
clean: rm -f $(OBJS) $(TARGET)清理規則,刪除生成的目標文件和可執行文件。
-
print 規則:
print: @echo "Source files: $(SRCS)" @echo "Object files: $(OBJS)"打印文件列表,使用
@符號避免輸出命令本身。 -
偽目標:
.PHONY: all clean print聲明
all、clean和print為偽目標,以避免與實際文件名發生沖突。偽目標用于告知make這些規則不生成文件,而是特殊的操作。因此,make會忽略它們的時間戳,總是執行這些規則。
2.5 常用命令
-
make:
make執行
Makefile中的默認規則(通常為all規則)。 -
make clean:
make clean執行
clean規則,清理生成的文件。 -
make -f 其他Makefile文件:
make -f other_makefile使用指定的
Makefile文件進行構建。
3. CMake
CMake 是一個跨平臺的構建系統,用于管理軟件的編譯過程。在大型項目中,手動管理編譯配置非常繁瑣,使用 CMake 可以簡化這一過程。CMake 通過 CMakeLists.txt 文件定義項目的構建規則。
3.1 基本結構
一個基本的 CMakeLists.txt 的結構如下:
- cmake_minimum_required:指定最低版本的
CMake。 - project:定義項目名稱。
- set:設置編譯選項和變量。
- include_directories:包含目錄。
- add_executable:生成可執行文件。
- add_library:生成庫文件(可選)。
- target_link_libraries:鏈接庫文件(可選)。
3.2 示例
假設有以下項目結構:
project/
├── include/
│ └── myheader.h
├── src/
│ ├── main.cpp
│ ├── file1.cpp
│ ├── file2.cpp
├── CMakeLists.txt
CMakeLists.txt 內容如下:
# CMake 最低版本要求
cmake_minimum_required(VERSION 3.10)
# 項目信息
project(MyProject)
# 指定 C++ 標準
set(CMAKE_CXX_STANDARD 11)
# 包含頭文件目錄
include_directories(include)
# 查找 src 目錄下的所有源文件
file(GLOB SRCS "src/*.cpp")
# 生成可執行文件
add_executable(myprogram ${SRCS})
3.3 變量
- CMAKE_CXX_STANDARD:指定 C++ 標準,如
11、14、17等。 - SRCS:源文件列表,由
file(GLOB)函數生成。
3.4 命令說明
-
cmake_minimum_required:
cmake_minimum_required(VERSION 3.10)指定最低版本的
CMake。 -
project:
project(MyProject)定義項目名稱。
-
set:
set(CMAKE_CXX_STANDARD 11)設置編譯選項,這里指定使用 C++11 標準。
-
include_directories:
include_directories(include)包含頭文件目錄。
-
file(GLOB):
file(GLOB SRCS "src/*.cpp")查找并設置源文件列表,
GLOB表示使用通配符匹配文件。 -
add_executable:
add_executable(myprogram ${SRCS})生成可執行文件
myprogram,并指定源文件列表。
3.5 常用命令
-
配置項目:
cmake .在當前目錄下生成構建文件。
-
生成項目:
make使用生成的構建文件進行編譯。
-
構建目錄:
mkdir build cd build cmake .. make創建一個單獨的構建目錄,進行 out-of-source 構建,保持源代碼目錄整潔。
-
清理項目:
手動刪除
build目錄或使用make clean命令(需在CMakeLists.txt中添加相應規則)。 -
打印源文件列表:
在調試時,可以添加
message命令以打印源文件列表,確保它們被正確識別:message(STATUS "Source files: ${SRCS}")
4. GDB
GDB(GNU 調試器)是一個強大的調試工具,用于調試 C、C++ 和其他語言編寫的程序。它可以在程序運行時設置斷點、檢查變量值、單步執行代碼等,幫助開發者找到并修復錯誤。
4.1 基本命令
-
啟動 GDB:
gdb program其中
program是要調試的可執行文件。 -
運行程序:
run啟動程序。如果程序需要參數,可以在
run命令后添加,例如run arg1 arg2。 -
設置斷點:
break [file:]function break [file:]line在指定函數或行設置斷點。例如:
break main break myfile.c:10 -
列出斷點:
info breakpoints顯示當前設置的斷點。
-
刪除斷點:
delete [breakpoint-number]刪除指定編號的斷點,如果不指定編號則刪除所有斷點。
-
單步執行:
step nextstep進入函數內部,next跳過函數調用。 -
繼續運行:
continue繼續執行程序,直到遇到下一個斷點。
-
打印變量值:
print variable打印變量的當前值。例如:
print x -
查看調用棧:
backtrace顯示當前的函數調用棧。
-
查看局部變量:
info locals顯示當前函數的局部變量。
4.2 示例
假設有以下 C 程序 example.c:
#include <stdio.h>
void function1() {
int x = 10;
printf("x = %d\n", x);
}
int main() {
function1();
return 0;
}
編譯程序,并啟用調試信息:
gcc -g -o example example.c
啟動 GDB 并調試程序:
gdb example
在 GDB 中執行以下命令:
-
運行程序:
run -
設置斷點:
break function1 -
繼續運行:
continue -
單步執行:
step -
打印變量值:
print x -
查看調用棧:
backtrace -
查看局部變量:
info locals

浙公網安備 33010602011771號