C語言編譯介紹—GCC編譯

編譯流程圖

?

編譯過程

1.預(yù)處理(Preprocessing),

2.編譯(Compilation),

3.匯編(Assemble),

4.鏈接(Linking)。

?

如下簡單入門程序:

// hello.c

#include <stdio.h>

int main()

{

? ? ? printf("hello world!\n");

}

通過gcc編譯

$ gcc hello.c # 編譯

$ ./a.out # 執(zhí)行

hello world!

預(yù)處理

第一個階段是預(yù)處理階段,在正式的編譯階段之前進(jìn)行。預(yù)處理階段將根據(jù)已放置在文件中的預(yù)處理指令來修改源文件的內(nèi)容抽诉。

1) 宏定義指令,如# define Name TokenString,# undef等盈滴。

對于前一個偽指令,預(yù)編譯所要做的是將程序中的所有Name用TokenString替換轿钠,但作為字符串常量的 Name則不被替換巢钓。對于后者,則將取消對某個宏的定義疗垛,使以后該串的出現(xiàn)不再被替換症汹。

2) 條件編譯指令,如# ifdef贷腕,# ifndef背镇,# else,# elif泽裳,# endif等瞒斩。

這些偽指令的引入使得程序員可以通過定義不同的宏來決定編譯程序?qū)δ男┐a進(jìn)行處理。預(yù)編譯程序?qū)⒏鶕?jù)有關(guān)的文件涮总,將那些不必要的代碼過濾掉胸囱。

3) 頭文件包含指令,如# include "FileName" 或者# include < FileName> 等瀑梗。

在頭文件中一般用偽指令# define定義了大量的宏(最常見的是字符常量)烹笔,同時包含有各種外部符號的聲明裳扯。

采用頭文件的目的主要是為了使某些定義可以供多個不同的C源程序使用。因為在需要用到這些定義的C源程序中谤职,只需加上一條# include語句即可嚎朽,而不必再在此文件中將這些定義重復(fù)一遍。預(yù)編譯程序?qū)杨^文件中的定義統(tǒng)統(tǒng)都加入到它所產(chǎn)生的輸出文件中柬帕,以供編譯程序?qū)χM(jìn)行處理哟忍。包含到c源程序中的頭文件可以是系統(tǒng)提供的,這些頭文件一般被放在/ usr/ include目錄下陷寝。在程序中# include它們要使用尖括號(< >)锅很。另外開發(fā)人員也可以定義自己的頭文件,這些文件一般與c源程序放在同一目錄下凤跑,此時在# include中要用雙引號("")爆安。

4) 特殊符號,預(yù)編譯程序可以識別一些特殊的符號仔引。

例如在源程序中出現(xiàn)的LINE標(biāo)識將被解釋為當(dāng)前行號(十進(jìn)制數(shù))扔仓,F(xiàn)ILE則被解釋為當(dāng)前被編譯的C源程序的名稱。預(yù)編譯程序?qū)τ谠谠闯绦蛑谐霈F(xiàn)的這些串將用合適的值進(jìn)行替換咖耘。

預(yù)編譯程序所完成的基本上是對源程序的“替代”工作翘簇。經(jīng)過此種替代,生成一個沒有宏定義儿倒、沒有條件編譯指令版保、沒有特殊符號的輸出文件。這個文件的含義同沒有經(jīng)過預(yù)處理的源文件是相同的夫否,但內(nèi)容有所不同彻犁。下一步,此輸出文件將作為編譯程序的輸入而被翻譯成為機器指令凰慈。

編譯

經(jīng)過預(yù)編譯得到的輸出文件中汞幢,只有常量;如數(shù)字微谓、字符串森篷、變量的定義,以及C語言的關(guān)鍵字堰酿,如main, if , else , for , while , { , } , + , - , * , \ 等等疾宏。編譯程序所要作得工作就是通過詞法分析和語法分析张足,在確認(rèn)所有的指令都符合語法規(guī)則之后触创,將其翻譯成等價的中間代碼表示或匯編代碼。優(yōu)化處理是編譯系統(tǒng)中一項比較艱深的技術(shù)为牍。它涉及到的問題不僅同編譯技術(shù)本身有關(guān)哼绑,而且同機器的硬件環(huán)境也有很大的關(guān)系岩馍。優(yōu)化一部分是對中間代碼的優(yōu)化。這種優(yōu)化不依賴于具體的計算機抖韩。另一種優(yōu)化則主要針對目標(biāo)代碼的生成而進(jìn)行的蛀恩。對于前一種優(yōu)化,主要的工作是刪除公共表達(dá)式茂浮、循環(huán)優(yōu)化(代碼外提双谆、強度削弱、變換循環(huán)控制條件席揽、已知量的合并等)顽馋、復(fù)寫傳播,以及無用賦值的刪除幌羞,等等寸谜。后一種類型的優(yōu)化同機器的硬件結(jié)構(gòu)密切相關(guān),最主要的是考慮是如何充分利用機器的各個硬件寄存器存放有關(guān)變量的值属桦,以減少對于內(nèi)存的訪問次數(shù)熊痴。另外,如何根據(jù)機器硬件執(zhí)行指令的特點(如流水線聂宾、RISC果善、CISC、VLIW等)而對指令進(jìn)行一些調(diào)整使目標(biāo)代碼比較短系谐,執(zhí)行的效率比較高岭埠,也是一個重要的研究課題。經(jīng)過優(yōu)化得到的匯編代碼必須經(jīng)過匯編程序的匯編轉(zhuǎn)換成相應(yīng)的機器指令蔚鸥,方可能被機器執(zhí)行惜论。

匯編

匯編過程實際上指把匯編語言代碼翻譯成目標(biāo)機器指令的過程。對于被翻譯系統(tǒng)處理的每一個C語言源程序止喷,都將最終經(jīng)過這一處理而得到相應(yīng)的目標(biāo)文件馆类。目標(biāo)文件中所存放的也就是與源程序等效的目標(biāo)的機器語言代碼。

目標(biāo)文件由段組成弹谁。通常一個目標(biāo)文件中至少有兩個段:

1) 代碼段:該段中所包含的主要是程序的指令乾巧。該段一般是可讀和可執(zhí)行的,但一般卻不可寫预愤。

2) 數(shù)據(jù)段:主要存放程序中要用到的各種全局變量或靜態(tài)的數(shù)據(jù)沟于。一般數(shù)據(jù)段都是可讀,可寫植康,可執(zhí)行的旷太。

UNIX環(huán)境下主要有三種類型的目標(biāo)文件:

1) 可重定位文件

其中包含有適合于其它目標(biāo)文件鏈接來創(chuàng)建一個可執(zhí)行的或者共享的目標(biāo)文件的代碼和數(shù)據(jù)。

2) 共享的目標(biāo)文件

這種文件存放了適合于在兩種上下文里鏈接的代碼和數(shù)據(jù)。第一種是鏈接程序可把它與其它可重定位文件及共享的目標(biāo)文件一起處理來創(chuàng)建另一個目標(biāo)文件供璧;第二種是動態(tài)鏈接程序?qū)⑺c另一個可執(zhí)行文件及其它的共享目標(biāo)文件結(jié)合到一起存崖,創(chuàng)建一個進(jìn)程映象。

3) 可執(zhí)行文件

它包含了一個可以被操作系統(tǒng)創(chuàng)建一個進(jìn)程來執(zhí)行之的文件睡毒。匯編程序生成的實際上是第一種類型的目標(biāo)文件来惧。對于后兩種還需要其他的一些處理方能得到,這個就是鏈接程序的工作了演顾。

鏈接

由匯編程序生成的目標(biāo)文件并不能立即就被執(zhí)行供搀,其中可能還有許多沒有解決的問題。

例如钠至,某個源文件中的函數(shù)可能引用了另一個源文件中定義的某個符號(如變量或者函數(shù)調(diào)用等)趁曼;在程序中可能調(diào)用了某個庫文件中的函數(shù),等等棕洋。所有的這些問題挡闰,都需要經(jīng)鏈接程序的處理方能得以解決。

鏈接程序的主要工作就是將有關(guān)的目標(biāo)文件彼此相連接掰盘,也即將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來摄悯,使得所有的這些目標(biāo)文件成為一個能夠被操作系統(tǒng)裝入執(zhí)行的統(tǒng)一整體。

1) 靜態(tài)鏈接

在這種鏈接方式下愧捕,函數(shù)的代碼將從其所在的靜態(tài)鏈接庫中被拷貝到最終的可執(zhí)行程序中奢驯。這樣該程序在被執(zhí)行時這些代碼將被裝入到該進(jìn)程的虛擬地址空間中。靜態(tài)鏈接庫實際上是一個目標(biāo)文件的集合次绘,其中的每個文件含有庫中的一個或者一組相關(guān)函數(shù)的代碼瘪阁。

2) 動態(tài)鏈接

在此種方式下,函數(shù)的代碼被放到稱作是動態(tài)鏈接庫或共享對象的某個目標(biāo)文件中邮偎。鏈接程序此時所作的只是在最終的可執(zhí)行程序中記錄下共享對象的名字以及其它少量的登記信息管跺。在此可執(zhí)行文件被執(zhí)行時,動態(tài)鏈接庫的全部內(nèi)容將被映射到運行時相應(yīng)進(jìn)程的虛地址空間禾进。動態(tài)鏈接程序?qū)⒏鶕?jù)可執(zhí)行程序中記錄的信息找到相應(yīng)的函數(shù)代碼豁跑。

實例

預(yù)處理器:將.c 文件轉(zhuǎn)化成 .i文件,使用的gcc命令是:gcc –E泻云,對應(yīng)于預(yù)處理命令cpp艇拍;

編譯器:將.c/.h文件轉(zhuǎn)換成.s文件,使用的gcc命令是:gcc –S宠纯,對應(yīng)于編譯命令 cc –S卸夕;

匯編器:將.s 文件轉(zhuǎn)化成 .o文件,使用的gcc命令是:gcc –c婆瓜,對應(yīng)于匯編命令是 as快集;

鏈接器:將.o文件轉(zhuǎn)化成可執(zhí)行程序,使用的gcc命令是: gcc,對應(yīng)于鏈接命令是 ld碍讨;

加載器:將可執(zhí)行程序加載到內(nèi)存并進(jìn)行執(zhí)行治力,loader和ld-linux.so蒙秒。

/ test.c

#include <stdio.h>

#include "mymath.h"http:// 自定義頭文件

int main(){

? ? int a = 2;

? ? int b = 3;

? ? int sum = add(a, b);

? ? printf("a=%d, b=%d, a+b=%d\n", a, b, sum);

}

// mymath.h

#ifndef MYMATH_H

#define MYMATH_H

int add(int a, int b){

? ? return a+b;

}

int sub(int a, int b){

? ? return a-b;

}

#endif

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勃黍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子晕讲,更是在濱河造成了極大的恐慌覆获,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓢省,死亡現(xiàn)場離奇詭異弄息,居然都是意外死亡,警方通過查閱死者的電腦和手機勤婚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門摹量,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人馒胆,你說我怎么就攤上這事缨称。” “怎么了祝迂?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵睦尽,是天一觀的道長。 經(jīng)常有香客問我型雳,道長当凡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任纠俭,我火速辦了婚禮沿量,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘冤荆。我一直安慰自己欧瘪,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布匙赞。 她就那樣靜靜地躺著佛掖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涌庭。 梳的紋絲不亂的頭發(fā)上芥被,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音坐榆,去河邊找鬼拴魄。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的匹中。 我是一名探鬼主播夏漱,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼顶捷!你這毒婦竟也來了挂绰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤服赎,失蹤者是張志新(化名)和其女友劉穎葵蒂,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體重虑,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡践付,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缺厉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片永高。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖提针,靈堂內(nèi)的尸體忽然破棺而出命爬,到底是詐尸還是另有隱情,我是刑警寧澤关贵,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布遇骑,位于F島的核電站,受9級特大地震影響揖曾,放射性物質(zhì)發(fā)生泄漏落萎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一炭剪、第九天 我趴在偏房一處隱蔽的房頂上張望练链。 院中可真熱鬧,春花似錦奴拦、人聲如沸媒鼓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绿鸣。三九已至,卻和暖如春暂氯,著一層夾襖步出監(jiān)牢的瞬間潮模,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工痴施, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留擎厢,地道東北人究流。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像动遭,于是被迫代替她去往敵國和親芬探。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容