簡單c程式
c code
#include
int main(int argc, char **argv)
過程
預處理
gcc -e -o main.i main.c
1. 展開所有巨集定義
2. 處理條件預編譯指令
3. 插入#include
執行的標頭檔案**
4. 新增行號和檔案標識, 以便編譯錯誤和警告的提示.
5. 刪除所有注釋
6. 新增其他資訊
編譯
gcc -s -o main.s main.i
對預處理完的檔案test.i
進行詞法分析, 語法分析, 語義分析以及優化後生成相應的彙編**.
彙編
gcc -c -o main.o main.s
將彙編**轉變成二進位制機器指令(根據彙編指令和機器指令對照表逐條翻譯), 最後產生目標檔案main.o
.
鏈結
gcc -o main main.o
gdb
編譯時使用gcc -g選項才能使用gdb除錯
自動化編譯鏈結檔案
makefile語句
目標檔案: 依賴檔案…
命令…makefile變數
宣告: var_name = var…
使用: $(var_name)
makefile特殊變數
$@
: 目標檔案
$^
: 被依賴的所有檔案
$<
: 被依賴的第乙個檔案
約定俗成的目標命令
all: 編譯所有目標
clean: 刪除make建立的檔案
install: 安裝已編譯好的程式
print: 列出改變過的原始檔
tar: 打包備份
dist: 建立乙個壓縮檔案
tags: 更新所有目標
防止和檔名衝突可以使用偽命令.phony
簡單makefile編寫
makefile code
cc = gcc
src = main.c
bin = main
$(bin):
$(src)
$(cc) -o $@
$^.phony
: clean
clean:
rm $(
bin)
靜態鏈結
優點: **裝載速度快, 執行速度比動態鏈結庫略快, 不需要外部函式庫支援
缺點: 檔案體積大, **冗餘造成記憶體浪費, 靜態函式庫發生改變時程式必須重新編譯.
動態鏈結
優點: 檔案體積小, 節省記憶體空間, 公升級方便, 提高軟體可維護性和可擴充套件性.
缺點: 程式變成多個部分, 更容易出錯.
要製作成庫的函式編寫
fun.c
c code
int fun(int a, int b)
main.c
c code
#include
#include
int main(int argc, char **argv)
靜態庫
製作靜態庫
ar -crs libfun.a fun.o
makefile code
cc = gcc
ar = ar
src_fun = fun.c
obj_fun = fun.o
lib_fun = libfun.a
src = main.c
bin = main
all:
$(obj_fun) $(
lib_fun) $(
bin)
$(obj_fun):
$(src_fun)
$(cc) -c -o $@
$^$(
lib_fun):
$(obj_fun)
$(ar) -crs $@
$^$(
bin):
$(src)
$(cc) -o $@
$^ -l. -lfun
.phony
: clean
clean:
rm $(
bin)
rm $(
obj_fun)
rm $(
lib_fun)
動態庫
製作動態庫
gcc -c -fpic -o fun.o fun.c
gcc -shared -o libfun.so fun.o
makefile code
cc = gcc
src_fun = fun.c
obj_fun = fun.o
lib_fun = libfun.so
src = main.c
bin = main
all:
$(obj_fun) $(
lib_fun) $(
bin)
$(obj_fun):
$(src_fun)
$(cc) -c -fpic -o $@
$^$(
lib_fun):
$(obj_fun)
$(cc) -shared -o $@
$^$(
bin):
$(src)
$(cc) -o $@
$^ -l. -lfun -wl,-rpath=.
.phony
: clean
clean:
rm $(
bin)
rm $(
obj_fun)
rm $(
lib_fun)
動態庫的鏈結方式還可以使用庫環境變數, 或者直接把庫放在系統的庫目錄中.
c語言執行時動態載入動態庫
需要鏈結dl庫
gcc -o main main.c -ldl
執行main程式
./main 3 4 ./libfun.so
c code
#include
#include
#include
int main(int argc, char **argv)
fn = dlsym(lib_handle, "fun");
err = dlerror();
if (err)
int a = atoi(argv[1]);
int b = atoi(argv[2]);
int ans = fn(a, b);
printf("%d\n", ans);
dlclose(lib_handle);
return
0;}
使用ldd
命令檢視二進位制程式所依賴的動態鏈結庫 鏈結 裝載與庫 2 編譯和鏈結
1 預處理 主要的處理規則如下 gcc e hello.c o hello.i e表示只進行預編譯2 編譯 將預處理完的檔案進行一系列的詞法分析 語法分析 語義分析和 優化。gcc s hello.c o hello.s 3 彙編 將彙編 轉換成機器碼 gcc c hello.s o hello.o...
鏈結 裝載與庫(2) 編譯和鏈結2 1
2.1 被隱藏了的過程 通常整合開發環境 ide 會將編譯和鏈結的過程一步完成,稱為構建 build 即時使用命令列來編譯乙個源 檔案,簡單地一句 gcc hello.c 命令實際上也包含了非常複雜的過程。乙個gcc過程可以分解為4個步驟,分別是預處理 prepressing 編譯 compilat...
編譯和鏈結
一般來說,無論是c c 首先要把原始檔編譯成中間 檔案,在windows下也就是 obj 檔案,unix下是 o 檔案,即 object file,這個動作叫做編譯 compile 然後再把大量的object file合成執行檔案,這個動作叫作鏈結 link 編譯時,編譯器需要的是語法的正確,函式與...