在ANSI C的任何一種實(shí)現(xiàn)中,存在兩個(gè)不同的環(huán)境。
第1種是翻譯環(huán)境,在這個(gè)環(huán)境中源代碼被轉(zhuǎn)換為可執(zhí)行的機(jī)器指令。
第2種是執(zhí)行環(huán)境,它用于實(shí)際執(zhí)行代碼
翻譯環(huán)境:
成都創(chuàng)新互聯(lián)公司長(zhǎng)期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為天門企業(yè)提供專業(yè)的成都做網(wǎng)站、網(wǎng)站建設(shè),天門網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。
展示了在Linux系統(tǒng)下程序的翻譯過(guò)程
1. 預(yù)處理 選項(xiàng) gcc -E test.c -o test.i
預(yù)處理完成之后就停下來(lái),預(yù)處理之后產(chǎn)生的結(jié)果都放在test.i文件中。
2. 編譯 選項(xiàng) gcc -S test.c
編譯完成之后就停下來(lái),結(jié)果保存在test.s中。
3. 匯編 gcc -c test.c
匯編完成之后就停下來(lái),結(jié)果保存在test.o中。
4.鏈接過(guò)程是根據(jù)程序所用函數(shù)的名稱,將C函數(shù)庫(kù)或其他函數(shù)庫(kù)中的函數(shù)鏈接到程序中,最終形成可執(zhí)行文件。
運(yùn)行環(huán)境:
程序執(zhí)行的過(guò)程:預(yù)處理指令 預(yù)定義符號(hào)
1. 程序必須載入內(nèi)存中。在有操作系統(tǒng)的環(huán)境中:一般這個(gè)由操作系統(tǒng)完成。在獨(dú)立的環(huán)境中,程序
的載入必須由手工安排,也可能是通過(guò)可執(zhí)行代碼置入只讀內(nèi)存來(lái)完成。
2. 程序的執(zhí)行便開(kāi)始。接著便調(diào)用main函數(shù)。
3.開(kāi)始執(zhí)行程序代碼。這個(gè)時(shí)候程序?qū)⑹褂靡粋€(gè)運(yùn)行時(shí)堆棧(stack),存儲(chǔ)函數(shù)的局部變量和返回
地址。程序同時(shí)也可以使用靜態(tài)(static)內(nèi)存,存儲(chǔ)于靜態(tài)內(nèi)存中的變量在程序的整個(gè)執(zhí)行過(guò)程
一直保留他們的值。
4. 終止程序。正常終止main函數(shù);也有可能是意外終止。
__FILE__ //進(jìn)行編譯的源文件
__LINE__ //文件當(dāng)前的行號(hào)
__DATE__ //文件被編譯的日期
__TIME__ //文件被編譯的時(shí)間
__STDC__ //如果編譯器遵循ANSI C,其值為1,否則未定義
用法:
printf("file:%s",__FILE__); //輸出當(dāng)前編譯的源文件名
printf("line:%d",__LINE__); //輸出當(dāng)前行號(hào)
printf("date:%s",__DATE__); //輸出文件被編譯的日期
printf("time:%s",__TIME__); //輸出文件被編譯的時(shí)間#define的用法定義標(biāo)識(shí)符
用法:
#define 名字 被定義的具體內(nèi)容
如:
#define MAX 100
#define name "張三"
定義宏
在 C 語(yǔ)言中,可以采用命令 #define 來(lái)定義宏。該命令允許把一個(gè)名稱指定成任何所需的文本,例如一個(gè)常量值或者一條語(yǔ)句。在定義了宏之后,無(wú)論宏名稱出現(xiàn)在源代碼的何處,預(yù)處理器都會(huì)把它用定義時(shí)指定的文本替換掉。 慣例將宏名稱每個(gè)字母采用大寫,這有助于區(qū)分宏與一般的變量。
用法:
#define 名字(參數(shù)列表) 被定義的具體內(nèi)容
例:
#define MAX(a,b) (a>b?a:b)
注意事項(xiàng):
參數(shù)列表的左括號(hào)必須與name緊鄰。
如果兩者之間有任何空白存在,參數(shù)列表就會(huì)被解釋為stuff的一部分
在程序中,如果我們想求出兩個(gè)數(shù)中的大值,通常一個(gè)方法就是編寫函數(shù)Max,計(jì)算結(jié)果并輸出;
同樣,該程序也可以采用定義宏來(lái)計(jì)算結(jié)果。
另外,為避免宏使用時(shí)出現(xiàn)爭(zhēng)議性錯(cuò)誤,還應(yīng)該注意它定義時(shí)的規(guī)范性
例如:
定義一個(gè)宏,求一個(gè)數(shù)的平方
#define SQUARE( x ) x * x
當(dāng)程序中出現(xiàn)
int a = 5;
printf("%d\n" ,SQUARE( a + 1) );
由于宏是直接替換,參數(shù)x被替換成a+1,所以該語(yǔ)句實(shí)際上是printf("%d\n",a+1*a+1);
代入a=5,經(jīng)計(jì)算結(jié)果為11,并非主觀上的6*6=36
經(jīng)修正:
宏應(yīng)該被定義為
#define SQUARE( x ) (x) * (x)
所以用于對(duì)數(shù)值表達(dá)式進(jìn)行求值的宏定義都應(yīng)該考慮充分,在合適的位置加上括號(hào),避免在使用宏時(shí)由于參數(shù)中的操作符或鄰近操作符之間不可預(yù)料的相互作用。
#和##的用法通過(guò)觀察發(fā)現(xiàn),C語(yǔ)言的字符串有自動(dòng)連接的特點(diǎn),即兩個(gè)“”緊密相連的字符串可以一并輸出
#define PRINT(FORMAT, VALUE)\
printf("the value is "FORMAT"\n", VALUE);
...
PRINT("%d", 10); //輸出結(jié)果是什么
這里的宏參數(shù)為“%d”和10,分別替換FORMAT 和 VALUE,其中FORMAT在傳參時(shí)必須傳入帶有“”的參數(shù),否則便不能輸出。
使用 # ,把一個(gè)宏參數(shù)變成對(duì)應(yīng)的字符串
上面代碼可更改為
#define PRINT(FORMAT, VALUE) printf("the value is "#FORMAT"\n", VALUE);
....
PRINT(%d, 10);
#FORMAT被預(yù)處理器預(yù)處理為"FORMAT"--->"%d"
##可以把位于它兩邊的符號(hào)合成一個(gè)符號(hào)。帶副作用的宏參數(shù)
它允許宏定義從分離的文本片段創(chuàng)建標(biāo)識(shí)符。
#define ADD_TO_SUM(num, value) sum##num += value;
...
ADD_TO_SUM(5, 10);
//先進(jìn)行宏替換-->sum##5+=10 ##將兩邊的符號(hào)合并-->sum5+=10 -->給sum5增加10.
當(dāng)宏參數(shù)在宏的定義中出現(xiàn)超過(guò)一次的時(shí)候,如果參數(shù)帶有副作用,那么你在使用這個(gè)宏的時(shí)候就可能
出現(xiàn)危險(xiǎn),導(dǎo)致不可預(yù)測(cè)的后果。副作用就是表達(dá)式求值的時(shí)候出現(xiàn)的永久性效果。
例如:
x+1 //無(wú)副作用,x沒(méi)有變化
x++ //有副作用,x本身會(huì)+1
思考下面宏替換后輸出的結(jié)果是什么?
#define MAX(a, b) ( (a) >(b) ? (a) : (b) )
...
x = 5;
y = 8;
z = MAX(x++, y++);
printf("x=%d y=%d z=%d\n", x, y, z);//輸出的結(jié)果是什么?
//6 9 9宏替換后,MAX(x++,y++)-->((x++)>(y++)?(x++):(y++))-->
((5++)>(8++)?(5++):(8++))-->9
在使用宏定義時(shí) 盡量不要使用 x++ 等會(huì)影響原來(lái)參數(shù)的值的宏參數(shù)
宏和函數(shù)的對(duì)比屬性 | #define定義宏 | 函數(shù) |
代碼長(zhǎng)度 | 程序中每次定義宏時(shí),都會(huì)將宏代碼替換到程序中。若宏的代碼過(guò)長(zhǎng)且程序中出現(xiàn)多段宏,則會(huì)增加代碼長(zhǎng)度。 | 函數(shù)的代碼只出現(xiàn)在一個(gè)地方,每次函數(shù)調(diào)用都會(huì)調(diào)用同一個(gè)地方的代碼,多次調(diào)用函數(shù)不會(huì)增加代碼長(zhǎng)度。 |
執(zhí)行速度 | 更快 | 函數(shù)的調(diào)用和返回消耗一定時(shí)間,會(huì)稍慢 |
操作符優(yōu)先級(jí) | 宏參數(shù)的求值是在所有周圍表達(dá)式的上下文環(huán)境里, 除非加上括號(hào),否則鄰近操作符的優(yōu)先級(jí)可能會(huì)產(chǎn)生 不可預(yù)料的后果,所以建議宏在書寫的時(shí)候多些括 號(hào)。 | 函數(shù)參數(shù)只在函數(shù)調(diào)用的時(shí)候求值一次,它的結(jié)果值傳遞給函數(shù)。表達(dá)式的求值結(jié)果更容易預(yù)測(cè)。 |
帶副作用的參數(shù) | 參數(shù)會(huì)被替換到宏的多個(gè)位置,所以應(yīng)該避免使用帶副作用的參數(shù) | 函數(shù)參數(shù)只在函數(shù)調(diào)用時(shí)求值一次,結(jié)果更易預(yù)測(cè) |
參數(shù)類型 | 宏的參數(shù)與類型無(wú)關(guān),只要對(duì)參數(shù)的操作是合法的,它就可以使用于任何參數(shù)類型。 | 函數(shù)的參數(shù)是與類型有關(guān)的,參數(shù)的類型不同,就需要不同 的函數(shù)。 |
調(diào)試 | 不方便 | 方便 |
遞歸 | 不可遞歸 | 可遞歸 |
移除前面#define NAME的宏定義
#undef NAME條件編譯
//如果現(xiàn)存的一個(gè)名字需要被重新定義,那么它的舊名字首先要被移除。
在編譯一個(gè)程序的時(shí)候我們?nèi)绻獙⒁粭l語(yǔ)句(一組語(yǔ)句)編譯或者放棄是很方便的。因?yàn)槲覀冇袟l件
編譯指令。比如在程序測(cè)試時(shí)想添加一些代碼,但測(cè)試過(guò)后不想刪除,可以采用更改其為注釋的方法,也可以使用條件編譯,僅讓其在測(cè)試時(shí)編譯。
常見(jiàn)的條件編譯指令:
1.單分支
#if 常量表達(dá)式
....
#endif
....
#define __DEBUG__ 1
#if __DEBUG__
printf("測(cè)試中。。。”);
#endif
printf("測(cè)試完畢”);2.多個(gè)分支的條件編譯
#if 常量表達(dá)式
...
#elif 常量表達(dá)式
...
#else
...
#endif
3.判斷是否被定義
//如果定義了symbol
#if defined(symbol)
#ifdef symbol
//如果沒(méi)有定義symbol
#if !defined(symbol)
#ifndef symbol
#define symbol 100
#ifdef symbol
printf("%d",symbol);
#ifndef symbol
printf("not define");4.嵌套指令
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
當(dāng)前題目:程序環(huán)境和預(yù)處理-創(chuàng)新互聯(lián)
當(dāng)前路徑:http://chinadenli.net/article22/cecjjc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、云服務(wù)器、ChatGPT、外貿(mào)建站、網(wǎng)站改版、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容