將c語(yǔ)言源代碼編譯成可執(zhí)行程序的過(guò)程包括以下幾個(gè)步驟,每一步都對(duì)源代碼進(jìn)行了不同的處理:
-
預(yù)處理(.c文件 -> .i文件)
目的:將頭文件和宏進(jìn)行替換,取消注釋。文件從 code.c 變?yōu)?code.i。
現(xiàn)在我使用指令對(duì) .c 文件進(jìn)行預(yù)處理,讓我們來(lái)看一下預(yù)處理后的代碼:
gcc -E code.c -o code.i
可以看到頭文件確實(shí)被庫(kù)
中的代碼替換了;而其他代碼保持不變。 注意:替換后的代碼仍然是c語(yǔ)言代碼,只是變得更加簡(jiǎn)潔(沒(méi)有注釋?zhuān)?/p>
-
編譯(.i文件 -> .s文件)
目的:將C語(yǔ)言代碼處理為匯編代碼。
這次我們直接使用預(yù)處理過(guò)的文件進(jìn)行下一步的匯編:
gcc -S code.i -o code.s
我們發(fā)現(xiàn)這次處理后的代碼已經(jīng)變成我們看不懂的了,這就是已經(jīng)從C代碼轉(zhuǎn)換為了匯編代碼。
-
匯編(.s文件 -> .o文件)
目的:進(jìn)一步處理匯編代碼,形成機(jī)器可識(shí)別的代碼(可重定向目標(biāo)文件)。
這次我們使用上一次的 code.s 文件繼續(xù)編譯,會(huì)報(bào)錯(cuò);所以我們這次使用 code.c 來(lái)進(jìn)行處理:
gcc -c code.c -o code.o
這次的代碼和上次的有變化,但還是看不懂。我們記住是從匯編代碼處理為了機(jī)器可識(shí)別的代碼,變成了可重定向目標(biāo)文件。
-
鏈接(.o文件 -> exe文件)
目的:產(chǎn)生可執(zhí)行文件。
這次使用 .o 文件鏈接為 exe 文件:
gcc code.o -o code
E、S、c選項(xiàng)先有語(yǔ)言還是先有編譯器?答案是先有語(yǔ)言,但并不是先有當(dāng)前編譯器的語(yǔ)言。在最早的時(shí)期,人們都是使用二進(jìn)制語(yǔ)言來(lái)編寫(xiě)程序的;然而,為了更加方便地編寫(xiě)代碼,人們使用二進(jìn)制編寫(xiě)了匯編代碼,因此匯編語(yǔ)言產(chǎn)生了。然后,人們又使用匯編代碼開(kāi)發(fā)出了匯編代碼編譯器,這個(gè)過(guò)程就叫做語(yǔ)言自舉。
動(dòng)態(tài)連接和靜態(tài)連接庫(kù)的位置,我們平時(shí)使用的頭文件都是聲明,實(shí)現(xiàn)都在庫(kù)文件中,庫(kù)一般都在 /usr/include 目錄下。
連接方式分為動(dòng)態(tài)鏈接和靜態(tài)連接。
查看文件使用的哪種庫(kù)?
根據(jù)紅色的部分判斷是什么庫(kù)?
云服務(wù)器默認(rèn)沒(méi)有安裝C/c++靜態(tài)標(biāo)準(zhǔn)庫(kù),我們可以使用 yum 按照下面的指令安裝:
sudo yum install libstdc++-static
Makefile自動(dòng)構(gòu)建工具
我們可以把 Makefile 理解為指令的集合;Makefile 文件里有我們寫(xiě)好的很多指令,然后我們對(duì) Makefile 進(jìn)行操作就可以更加便捷地調(diào)用其內(nèi)部的指令。
舉個(gè)例子,比如有一份 proc.c 的C語(yǔ)言文件,在使用的過(guò)程中需要多次對(duì)文件編譯,通常情況下每次編譯都要使用 gcc proc.c -o proc 生成可執(zhí)行文件 proc;這樣操作是很麻煩的。Makefile 工具可以很好地解決這種頻繁調(diào)用編譯的問(wèn)題。
Makefile 的使用:
第一行:proc 是生成的文件,proc.c 是依賴(lài)文件;冒號(hào)代表的是依賴(lài)關(guān)系。第二行需要空一個(gè) Tab 鍵的長(zhǎng)度(不能使用空格),然后輸入要執(zhí)行的命令。
我們直接使用指令 make 就可以調(diào)用 gcc proc.c -o proc 指令了,這樣使用起來(lái)是不是會(huì)很方便?
那是不是也可以這樣方便地清理文件呢?
答案是可以的:
不同的是刪除代碼不需要依賴(lài)任何文件,所以沒(méi)有依賴(lài)文件。我們需要使用 make clean 來(lái)調(diào)用清除可執(zhí)行程序的指令。
為什么 gcc proc.c -o proc 直接使用 make 就可以呢?
這是因?yàn)榇a的執(zhí)行順序是從上到下的,make 默認(rèn)調(diào)用第一個(gè)依賴(lài)關(guān)系命令,這里實(shí)際上 make 的完整指令應(yīng)該是 make proc。
目標(biāo)的調(diào)用順序
現(xiàn)在來(lái)寫(xiě)一下C語(yǔ)言編譯的完整過(guò)程:
程序執(zhí)行的順序是從上往下執(zhí)行的,當(dāng)執(zhí)行 gcc proc.o -o proc 時(shí),這時(shí)候還沒(méi)有 proc.o 文件,所以就會(huì)先把這一行的指令放入堆棧中,依次類(lèi)推,直到最后 gcc -E proc.c -o proc.i 產(chǎn)生了 proc.i 文件,緊接著指令依次出棧;最后執(zhí)行完畢。
.PHONY偽目標(biāo)
在沒(méi)有使用 .PHONY 的情況下,proc.c 文件在最新版本時(shí),只能 make 一次。這樣做的目的是提高效率。
在此編譯會(huì)給出“proc is up to date”,proc 可執(zhí)行程序是最新的,不需要再次編譯。
如何查看文件是否是最新的?
stat 文件名:查看文件的最近一次的更改時(shí)間相關(guān)的信息。正常情況下,proc.c 文件的時(shí)間應(yīng)該是在 proc 之前的,因?yàn)橄扔?proc.c 再有 proc;這是我剛才更新了一下 proc.c 文件,這時(shí)候 proc.c 比 proc 還要新,所以這個(gè)時(shí)候是可以重新編譯的。
使用偽目標(biāo)忽略時(shí)間:
如果我們對(duì) make proc 設(shè)置偽目標(biāo),那樣就可以無(wú)限次地編譯了。
總結(jié)