C語(yǔ)言程序的編譯與預(yù)處理詳解
一、程序的編譯
我們寫(xiě)的源文件(*.c)是經(jīng)過(guò)怎樣的處理生產(chǎn)可執(zhí)行文件(*.exe)的呢?這種處理有兩個(gè)步驟—編譯和鏈接。源文件在編譯階段通過(guò)編譯器將每個(gè)源文件轉(zhuǎn)換為目標(biāo)文件(這些文件是可執(zhí)行的機(jī)器指令),再通過(guò)鏈接器將其捆綁到一起,生成一個(gè)完整的可執(zhí)行程序。
1、 編譯階段
編譯階段可細(xì)分為3個(gè)階段:預(yù)處理(即預(yù)編譯)、編譯、匯編
預(yù)處理:主要進(jìn)行頭文件的包含、處理預(yù)處理指令(如:#define定義符號(hào)的替換)、刪除注釋。此時(shí)(*.c)文件轉(zhuǎn)換為(*.i)文件。
編譯:主要進(jìn)行語(yǔ)法分析、詞法分析、語(yǔ)義分析、符號(hào)匯總,此階段會(huì)將c語(yǔ)言代碼轉(zhuǎn)換為匯編代碼。此時(shí)(*.i)文件轉(zhuǎn)換為(*.s)文件。
匯編:此階段會(huì)形成符號(hào)表,將匯編代碼轉(zhuǎn)換為二進(jìn)制指令(機(jī)器指令)。此時(shí)(*.s)文件轉(zhuǎn)換為(*.o)文件。
2、鏈接
此階段主要完成合并段表、符號(hào)表的合并和重定位工作,將(*.o)文件鏈接到一起生成可執(zhí)行文件。
二、預(yù)處理詳解
1、預(yù)定義符號(hào)
__FILE__ //進(jìn)行編譯的源文件 __LINE__ //文件當(dāng)前的行號(hào) __DATE__ //文件被編譯的日期 __TIME__ //文件被編譯的時(shí)間 __STDC__ //如果編譯器遵循ANSI C,其值為1;如果不遵循,則編譯器不認(rèn)識(shí)這個(gè)符號(hào),是個(gè)未定義標(biāo)識(shí)符,此時(shí)使用這個(gè)符號(hào)程序會(huì)報(bào)錯(cuò)。該符號(hào)的作用是判斷編譯器是否遵循ANSI C。
下面為大家展示這些符號(hào)的作用。
執(zhí)行結(jié)果為:
2、#define定義的標(biāo)識(shí)符
語(yǔ)法:
#define MAX 100
這句代碼的意思是數(shù)字“100”替換成符號(hào)MAX,例如:
#include <stdio.h> #define MAX 100 int main() { int i = 1 + MAX; printf("%d", i); return 0; }
結(jié)果:
注意:define定義的標(biāo)識(shí)符只進(jìn)行替換,并不會(huì)在替換過(guò)程中執(zhí)行運(yùn)算,例如
#include <stdio.h> #define MAX 5+5 int main() { int i = 10; int x = i * MAX; printf("%d", x); return 0; }
這個(gè)程序的結(jié)果是多少呢?100嗎?答案其實(shí)是55,因?yàn)閐efine只是簡(jiǎn)單的替換,i*MAX其實(shí)本質(zhì)是i*5+5,即10*5+5=55.
3、#define定義的宏
語(yǔ)法:
#define SQUARE(x) x * x
當(dāng)我們?cè)诔绦蛑袑?xiě)下:SQUARE(5)這句代碼,這預(yù)處理時(shí),這句代碼就會(huì)被替換成5*5。例如:
#include <stdio.h> #define SQUARE(x) (x) * (x) int main() { int i = SQUARE(5); printf("%d", i); return 0; }
程序結(jié)果為:
注意:同樣的#define定義的宏也只是進(jìn)行簡(jiǎn)單的替換。
例如:
#include <stdio.h> #define SQUARE(x) x * x int main() { int a = 5; int i = SQUARE(a+1); printf("%d", i); return 0; }
這個(gè)程序的結(jié)果是什么呢?答案是11,SQUARE(a+1)等同于SQUARE(5+1),即5+1*5+1=11,而不是6*6=36。
宏常常被用于執(zhí)行簡(jiǎn)單的運(yùn)算,比如在兩個(gè)數(shù)中找出較大的一個(gè)。
#define MAX(a, b) ((a)>(b)?(a):(b))
那么為什么不用函數(shù)呢,因?yàn)楹暧袃蓚€(gè)優(yōu)勢(shì):
1. 用于調(diào)用函數(shù)和從函數(shù)返回的代碼可能比實(shí)際執(zhí)行這個(gè)小型計(jì)算工作所需要的時(shí)間更多。所以宏比函數(shù)在程序 的規(guī)模和速度方面更勝一籌。
2. 更為重要的是函數(shù)的參數(shù)必須聲明為特定的類(lèi)型。所以函數(shù)只能在類(lèi)型合適的表達(dá)式上使用。反之這個(gè)宏怎可 以適用于整形、長(zhǎng)整型、浮點(diǎn)型等可以用于>來(lái)比較的類(lèi)型。宏是類(lèi)型無(wú)關(guān)的。
但宏也有劣勢(shì):
1. 每次使用宏的時(shí)候,一份宏定義的代碼將插入到程序中。除非宏比較短,否則可能大幅度增加程序的長(zhǎng)度。
2. 宏是沒(méi)法調(diào)試的。
3. 宏由于類(lèi)型無(wú)關(guān),也就不夠嚴(yán)謹(jǐn)
4. 宏可能會(huì)帶來(lái)運(yùn)算符優(yōu)先級(jí)的問(wèn)題,導(dǎo)致程容易出現(xiàn)錯(cuò)。(就是上面我提醒大家需要注意的地方)
4、#unef
這條指令用于移除一個(gè)#define定義標(biāo)識(shí)符或宏定義。
例如:
#define MAX 100 int main() { int m = MAX; #undef MAX int n = MAX;//err return 0; }
這個(gè)程序會(huì)報(bào)錯(cuò),因?yàn)槟莻€(gè)int n=MAX中的MAX的定義被移除了,而其他的不會(huì)(m仍然是正確的)。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
opencv實(shí)現(xiàn)機(jī)器視覺(jué)檢測(cè)和計(jì)數(shù)的方法
在機(jī)器視覺(jué)中,有時(shí)需要對(duì)產(chǎn)品進(jìn)行檢測(cè)和計(jì)數(shù)。其難點(diǎn)無(wú)非是對(duì)于產(chǎn)品的圖像分割。本文就來(lái)介紹一下機(jī)器視覺(jué)檢測(cè)和計(jì)數(shù)的實(shí)現(xiàn),感興趣的可以參考一下2021-05-05C語(yǔ)言中用于產(chǎn)生隨機(jī)數(shù)的函數(shù)使用方法總結(jié)
這篇文章主要介紹了C語(yǔ)言中用于產(chǎn)生隨機(jī)數(shù)的函數(shù)使用方法總結(jié),分別介紹了rand()函數(shù)和srand()函數(shù)以及封裝出的arc4random()函數(shù),需要的朋友可以參考下2016-05-05C/C++如何實(shí)現(xiàn)循環(huán)左移,循環(huán)右移
這篇文章主要介紹了C/C++如何實(shí)現(xiàn)循環(huán)左移,循環(huán)右移,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07C語(yǔ)言 經(jīng)典題目螺旋矩陣 實(shí)例詳解
這篇文章主要介紹了C語(yǔ)言 經(jīng)典題目螺旋矩陣 實(shí)例詳解的相關(guān)資料,這里附有代碼實(shí)例及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-12-12將正小數(shù)轉(zhuǎn)化為2-9進(jìn)制小數(shù)的實(shí)現(xiàn)方法
本篇文章對(duì)正小數(shù)轉(zhuǎn)化為2-9進(jìn)制小數(shù)的實(shí)現(xiàn)方法進(jìn)行了介紹,需要的朋友參考下2013-05-05C語(yǔ)言scandir函數(shù)獲取文件夾內(nèi)容的實(shí)現(xiàn)
scandir?函數(shù)用于列舉指定目錄下的文件列表,本文主要介紹了C語(yǔ)言scandir函數(shù)獲取文件夾內(nèi)容的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03C++實(shí)現(xiàn)LeetCode(87.攪亂字符串)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(87.攪亂字符串),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07