程序環(huán)境和預(yù)處理-創(chuàng)新互聯(lián)

C語言程序的編譯+鏈接
在ANSI C的任何一種實現(xiàn)中,存在兩個不同的環(huán)境。
第1種是翻譯環(huán)境,在這個環(huán)境中源代碼被轉(zhuǎn)換為可執(zhí)行的機器指令。
第2種是執(zhí)行環(huán)境,它用于實際執(zhí)行代碼

翻譯環(huán)境:

成都創(chuàng)新互聯(lián)公司長期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為天門企業(yè)提供專業(yè)的成都做網(wǎng)站、網(wǎng)站建設(shè),天門網(wǎng)站改版等技術(shù)服務(wù)。擁有10余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

展示了在Linux系統(tǒng)下程序的翻譯過程

1. 預(yù)處理 選項 gcc -E test.c -o test.i

預(yù)處理完成之后就停下來,預(yù)處理之后產(chǎn)生的結(jié)果都放在test.i文件中。

2. 編譯 選項 gcc -S test.c

編譯完成之后就停下來,結(jié)果保存在test.s中。

3. 匯編 gcc -c test.c

匯編完成之后就停下來,結(jié)果保存在test.o中。

4.鏈接過程是根據(jù)程序所用函數(shù)的名稱,將C函數(shù)庫或其他函數(shù)庫中的函數(shù)鏈接到程序中,最終形成可執(zhí)行文件。

運行環(huán)境:

程序執(zhí)行的過程:
1. 程序必須載入內(nèi)存中。在有操作系統(tǒng)的環(huán)境中:一般這個由操作系統(tǒng)完成。在獨立的環(huán)境中,程序
的載入必須由手工安排,也可能是通過可執(zhí)行代碼置入只讀內(nèi)存來完成。
2. 程序的執(zhí)行便開始。接著便調(diào)用main函數(shù)。
3.開始執(zhí)行程序代碼。這個時候程序?qū)⑹褂靡粋€運行時堆棧(stack),存儲函數(shù)的局部變量和返回
地址。程序同時也可以使用靜態(tài)(static)內(nèi)存,存儲于靜態(tài)內(nèi)存中的變量在程序的整個執(zhí)行過程
一直保留他們的值。
4. 終止程序。正常終止main函數(shù);也有可能是意外終止。
預(yù)處理指令 預(yù)定義符號
__FILE__ //進(jìn)行編譯的源文件
__LINE__ //文件當(dāng)前的行號
__DATE__ //文件被編譯的日期
__TIME__ //文件被編譯的時間
__STDC__ //如果編譯器遵循ANSI C,其值為1,否則未定義

用法:

printf("file:%s",__FILE__); //輸出當(dāng)前編譯的源文件名
printf("line:%d",__LINE__); //輸出當(dāng)前行號
printf("date:%s",__DATE__); //輸出文件被編譯的日期
printf("time:%s",__TIME__); //輸出文件被編譯的時間
#define的用法
  1. 定義標(biāo)識符

用法:
#define 名字 被定義的具體內(nèi)容
如:
#define MAX 100
#define name "張三"

  1. 定義宏

在 C 語言中,可以采用命令 #define 來定義宏。該命令允許把一個名稱指定成任何所需的文本,例如一個常量值或者一條語句。在定義了宏之后,無論宏名稱出現(xiàn)在源代碼的何處,預(yù)處理器都會把它用定義時指定的文本替換掉。 慣例將宏名稱每個字母采用大寫,這有助于區(qū)分宏與一般的變量。
用法:
#define 名字(參數(shù)列表) 被定義的具體內(nèi)容
例:
#define MAX(a,b) (a>b?a:b)
注意事項:
參數(shù)列表的左括號必須與name緊鄰。
如果兩者之間有任何空白存在,參數(shù)列表就會被解釋為stuff的一部分

在程序中,如果我們想求出兩個數(shù)中的大值,通常一個方法就是編寫函數(shù)Max,計算結(jié)果并輸出;

同樣,該程序也可以采用定義宏來計算結(jié)果。

另外,為避免宏使用時出現(xiàn)爭議性錯誤,還應(yīng)該注意它定義時的規(guī)范性

例如:

定義一個宏,求一個數(shù)的平方
#define SQUARE( x ) x * x
當(dāng)程序中出現(xiàn)
int a = 5;
printf("%d\n" ,SQUARE( a + 1) );
由于宏是直接替換,參數(shù)x被替換成a+1,所以該語句實際上是printf("%d\n",a+1*a+1);
代入a=5,經(jīng)計算結(jié)果為11,并非主觀上的6*6=36
經(jīng)修正:
宏應(yīng)該被定義為
#define SQUARE( x ) (x) * (x)

所以用于對數(shù)值表達(dá)式進(jìn)行求值的宏定義都應(yīng)該考慮充分,在合適的位置加上括號,避免在使用宏時由于參數(shù)中的操作符或鄰近操作符之間不可預(yù)料的相互作用。

#和##的用法

通過觀察發(fā)現(xiàn),C語言的字符串有自動連接的特點,即兩個“”緊密相連的字符串可以一并輸出

#define PRINT(FORMAT, VALUE)\
 printf("the value is "FORMAT"\n", VALUE);
...
PRINT("%d", 10); //輸出結(jié)果是什么

這里的宏參數(shù)為“%d”和10,分別替換FORMAT 和 VALUE,其中FORMAT在傳參時必須傳入帶有“”的參數(shù),否則便不能輸出。

使用 # ,把一個宏參數(shù)變成對應(yīng)的字符串
上面代碼可更改為
#define PRINT(FORMAT, VALUE) printf("the value is "#FORMAT"\n", VALUE);
....
PRINT(%d, 10);

#FORMAT被預(yù)處理器預(yù)處理為"FORMAT"--->"%d"

##可以把位于它兩邊的符號合成一個符號。
它允許宏定義從分離的文本片段創(chuàng)建標(biāo)識符。
#define ADD_TO_SUM(num, value) sum##num += value;
...
ADD_TO_SUM(5, 10);
//先進(jìn)行宏替換-->sum##5+=10 ##將兩邊的符號合并-->sum5+=10 -->給sum5增加10.
帶副作用的宏參數(shù)

當(dāng)宏參數(shù)在宏的定義中出現(xiàn)超過一次的時候,如果參數(shù)帶有副作用,那么你在使用這個宏的時候就可能

出現(xiàn)危險,導(dǎo)致不可預(yù)測的后果。副作用就是表達(dá)式求值的時候出現(xiàn)的永久性效果。

例如:
x+1 //無副作用,x沒有變化
x++ //有副作用,x本身會+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

在使用宏定義時 盡量不要使用 x++ 等會影響原來參數(shù)的值的宏參數(shù)

宏和函數(shù)的對比

屬性

#define定義宏

函數(shù)

代碼長度

程序中每次定義宏時,都會將宏代碼替換到程序中。若宏的代碼過長且程序中出現(xiàn)多段宏,則會增加代碼長度。

函數(shù)的代碼只出現(xiàn)在一個地方,每次函數(shù)調(diào)用都會調(diào)用同一個地方的代碼,多次調(diào)用函數(shù)不會增加代碼長度。

執(zhí)行速度

更快

函數(shù)的調(diào)用和返回消耗一定時間,會稍慢

操作符優(yōu)先級

宏參數(shù)的求值是在所有周圍表達(dá)式的上下文環(huán)境里,

除非加上括號,否則鄰近操作符的優(yōu)先級可能會產(chǎn)生

不可預(yù)料的后果,所以建議宏在書寫的時候多些括

號。

函數(shù)參數(shù)只在函數(shù)調(diào)用的時候求值一次,它的結(jié)果值傳遞給函數(shù)。表達(dá)式的求值結(jié)果更容易預(yù)測。

帶副作用的參數(shù)

參數(shù)會被替換到宏的多個位置,所以應(yīng)該避免使用帶副作用的參數(shù)

函數(shù)參數(shù)只在函數(shù)調(diào)用時求值一次,結(jié)果更易預(yù)測

參數(shù)類型

宏的參數(shù)與類型無關(guān),只要對參數(shù)的操作是合法的,它就可以使用于任何參數(shù)類型。

函數(shù)的參數(shù)是與類型有關(guān)的,參數(shù)的類型不同,就需要不同

的函數(shù)。

調(diào)試

不方便

方便

遞歸

不可遞歸

可遞歸

#undef

移除前面#define NAME的宏定義

#undef NAME
//如果現(xiàn)存的一個名字需要被重新定義,那么它的舊名字首先要被移除。
條件編譯
在編譯一個程序的時候我們?nèi)绻獙⒁粭l語句(一組語句)編譯或者放棄是很方便的。因為我們有條件
編譯指令。比如在程序測試時想添加一些代碼,但測試過后不想刪除,可以采用更改其為注釋的方法,也可以使用條件編譯,僅讓其在測試時編譯。

常見的條件編譯指令:

1.單分支

#if 常量表達(dá)式
....
#endif
....
#define __DEBUG__  1
#if __DEBUG__
printf("測試中。。?!?;
#endif
printf("測試完畢”);

2.多個分支的條件編譯

#if 常量表達(dá)式
...
#elif 常量表達(dá)式
...
#else
...
#endif

3.判斷是否被定義

//如果定義了symbol
#if defined(symbol)
#ifdef symbol
//如果沒有定義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海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前題目:程序環(huán)境和預(yù)處理-創(chuàng)新互聯(lián)
當(dāng)前路徑:http://muchs.cn/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)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管