Linux環境(gcc編譯器):C編程基礎操作
gcc安裝
Ubuntu:
sudo apt-get install gcc
Centos:
sudo yum install gcc
確認是否安裝成功
gcc -v
gcc基礎編譯命令
通過gcc編譯命令可以生成後綴名.i的預處理文件,.s的彙編文件,.o的目標文件,.a/.so的庫文件和可執行文件
Linux中的C程序源碼編譯成可執行程序,可能需要依賴多個庫文件。可以把這些依賴的庫文件當作源碼文件的一部分。
常用gcc命令參數
-c 後接編譯源文件名
-o 後接產生的目標文件
-g 表示在目標文件中產生調試信息,使得目標文件可以用於 gdb 調試
-D<宏定義> 編譯時將宏定義參數傳入進去
-Wall 打開所有類型的警告
生成可執行文件的方式
- 若干源碼文件 直接編譯生成可執行文件
格式:gcc [源碼文件名] -o [可執行文件名]
eg.gcc c1.c c2.c -o test.exe
- 源碼文件生成目標文件,目標文件和依賴的庫文件(可以省略)一起鏈接生成可執行文件
格式:
gcc -c [源碼文件名] -o [目標文件名]
gcc -o [可執行文件] [源碼文件] -[庫文件]
gcc -c c1.c -o c1.o gcc -c c2.c -o c2.o gcc -o test.exe c1.o c2.o
- 源碼文件生成預處理文件,預處理文件生成彙編文件,彙編文件生成目標文件,目標文件鏈接成可執行文件
gcc -E main.c -o main.i gcc -S main.i -o main.s gcc -c main.s -o main.o gcc -o main.exe main.o
gcc進階命令:靜態庫與動態庫文件的生成
-
靜態庫文件生成
靜態庫生成較爲簡單,庫文件在鏈接時直接注入源碼文件,生成的可執行文件移植性好,運行時不依賴靜態庫文件,方便部署,但是不利於升級,每次升級後需要重新生成可執行文件
生成流程:- gcc編譯命令生成目標文件
gcc -c add.c -o add.o
- ar命令對目標文件(可以是多個)打包生成庫文件 crsv爲參數,其中csv是修飾符可以省略
ar crsv libadd.a add.o
- 庫文件放入默認庫文件路徑/lib或/usr/lib
mv libadd.a /lib
- 編譯生成可執行文件,注意庫文件名
gcc -o main.exe main.c -ladd
- gcc編譯命令生成目標文件
其中,只有第二步需要記憶,其他均爲常規操作。
-
動態庫文件生成
動態庫生成稍微複雜,庫文件在鏈接時不注入源碼文件,生成的可執行文件運行時需要依賴動態庫文件,移植性差,不便於部署在其他機器,但是升級方便,只需要更新庫文件。
生成流程: -
動態編譯生成目標文件
gcc -fPIC -Wall -c add.c
-
目標文件生成動態庫文件
gcc -shared -o libadd.so add.o
-
庫文件放入默認庫文件路徑/lib或/usr/lib
mv libadd.so /lib
-
編譯生成可執行文件,注意庫文件名
gcc -o main.exe main.c -ladd
需要注意的是第一步和第二步也可以合成一步gcc -fPIC -Wall -shared -o libadd.so add.c
批量編譯:Makefile簡介
通過編寫Makefile文件可以實現批量編譯操作
原理:每次編譯過程使用的命令大體相同,不同的只有文件名,所以可以使用變量名替換掉文件名,從而實現自動化編譯。不同的文件之間存在依賴關係,所以採用自頂(可執行文件)向下(源碼文件)的遞歸過程。
Makefile的語法規則:
-
變量命名 :Makefile實際上是採用不同字符串對命令進行替換實現的,所以變量均爲字符串格式。爲了與命令區別,變量使用時需要加小括號並使用$進行標識:$(變量名)
- 直接賦值定義:
變量名:= 字符串
- 遞歸式定義 :
變量名 = 字符串(變量名)
類似多個指針指向一個地址
- 直接賦值定義:
-
函數:
- 查找函數$(wildcard *.c),wildcard是函數名,後跟一個參數,作用是將符合該參數規則的文件名當作一列字符串輸出,各個文件名之間會隔開。*.c會找到當前目錄下的所有.c文件名並輸出
- 字符串替換函數$(patsubst 匹配規則1,匹配規則2,源字符串列表)將源字符串列表中符合匹配規則1的字符串 進行替換 使其符合匹配規則2。Makefile中的通配符爲%。
示例:
OC=$(patsubst %.c,%.o,$(wildcard *.*))
含義是將當前目錄下所有有後綴名的文件中的.c文件名拿出來,並把.c替換成.o,然後將這一串字符串賦值給變量OC -
規則
主要用到 :- $@代表當前規則下的目標文件\
- $^代表當前規則的所有依賴文件
- 所有的.o文件會自動依賴同名的.c文件
- 一系列的預定義變量
通過上述規則,即可編寫通用的makefile文件,針對特殊需求只需要修改對應變量即可
以下爲簡單的通用Makefile文件示例
生成可執行文件的Makefile文件
EXE:=test.exe
#編譯後得到的可執行文件的名字
CC:=gcc
#選擇的C編譯器 可以根據需要改動
CFLAGS:=-Wall -g
#gcc編譯參數 顯示所有警告信息 可調試 可以根據需要改動
LIBSO:=
#庫依賴文件 可以根據需要添加
OC := $(patsubst %.c, %.o, $(wildcard *.c))
#目標文件列表 用來生成可執行文件
$(EXE):$(OC)
$(CC) $(CFLAGS) -o $@ $^
.PHONY : clean rebuild
clean:
rm -f $(EXE) $(OC)
rebuild:
clean $(EXE)
生成靜態庫文件的Makefile文件
# 庫文件名, lib*.a
TARGET := libtest.a
# 編譯器選擇
CC := gcc
#打包程序選擇
AR = ar
#gcc編譯參數 顯示所有警告信息 可調試 可以根據需要改動
CFLAGS:=-Wall -g
#依賴的庫文件
LIBS :=
# 自動查找當前目錄所有 .c 文件,並將目標定義爲同名 .o 文件
SOURCE := $(wildcard *.c)
OBJS := $(patsubst %.c,%.o,$(SOURCE))
$(TARGET) : $(OBJS)
#生成靜態庫文件
$(AR) crvs $(TARGET) $(OBJS)
#移動到/lib中
mv $(TARGET) /lib
.PHONY : clean delete rebuild
clean :
#刪除中間文件
rm -rf *.o
#刪除庫文件
delete:
rm /lib/$(TARGET)
#重新生成庫文件
rebuild:
clean $(TARGET)
生成動態庫文件的Makefile文件
# 庫文件名, lib*.so
TARGET := libtest.so
# 編譯器選擇
CC := gcc
#gcc生成動態庫文件的編譯參數
CFLAGS:= -g -Wall -fPIC -shared -o
#依賴的庫文件
LIBS :=
# 自動查找當前目錄所有 .c 文件
SOURCE := $(wildcard *.c)
$(TARGET) : $(OBJS)
$(TARGET) $(CFLAGS) $(TARFET) $(SOURCE)
#移動到/lib中
mv $(TARGET) /lib
.PHONY : clean delete rebuild
clean :
#刪除中間文件
rm -rf *.o
#刪除庫文件
delete:
rm /lib/$(TARGET)
#重新生成庫文件
rebuild:
clean $(TARGET)
gcc調試命令gdb
如果在gcc編譯程序時加入了-g參數,則可以使用gdb命令對可執行文件進行調試
gdb -q 可執行文件名
#-q參數可以消除gdb啓動時輸出的無用的版本信息等
常用gdb命令:
l:查看代碼
b : 打斷點
info b:查看所有斷點
tb :打臨時斷點
r :運行
bt:查看函數堆棧調用信息
delete:刪除斷點
n:下一步,遇到函數直接執行不進入
s:下一步,遇到函數進入
disable:使某個斷點失效
enble:啓用某個斷點
c:繼續運行
p:打印命令,可以用來打印變量
q:退出