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

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

翻譯環(huán)境:

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

展示了在Linux系統下程序的翻譯過程

1. 預處理 選項 gcc -E test.c -o test.i

預處理完成之后就停下來,預處理之后產生的結果都放在test.i文件中。

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

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

3. 匯編 gcc -c test.c

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

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

運行環(huán)境:

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

用法:

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

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

  1. 定義宏

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

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

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

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

例如:

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

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

#和##的用法

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

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

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

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

#FORMAT被預處理器預處理為"FORMAT"--->"%d"

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

當宏參數在宏的定義中出現超過一次的時候,如果參數帶有副作用,那么你在使用這個宏的時候就可能

出現危險,導致不可預測的后果。副作用就是表達式求值的時候出現的永久性效果。

例如:
x+1 //無副作用,x沒有變化
x++ //有副作用,x本身會+1

思考下面宏替換后輸出的結果是什么?

#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);//輸出的結果是什么?
//6 9 9

宏替換后,MAX(x++,y++)-->((x++)>(y++)?(x++):(y++))-->

((5++)>(8++)?(5++):(8++))-->9

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

宏和函數的對比

屬性

#define定義宏

函數

代碼長度

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

函數的代碼只出現在一個地方,每次函數調用都會調用同一個地方的代碼,多次調用函數不會增加代碼長度。

執(zhí)行速度

更快

函數的調用和返回消耗一定時間,會稍慢

操作符優(yōu)先級

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

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

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

號。

函數參數只在函數調用的時候求值一次,它的結果值傳遞給函數。表達式的求值結果更容易預測。

帶副作用的參數

參數會被替換到宏的多個位置,所以應該避免使用帶副作用的參數

函數參數只在函數調用時求值一次,結果更易預測

參數類型

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

函數的參數是與類型有關的,參數的類型不同,就需要不同

的函數。

調試

不方便

方便

遞歸

不可遞歸

可遞歸

#undef

移除前面#define NAME的宏定義

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

常見的條件編譯指令:

1.單分支

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

2.多個分支的條件編譯

#if 常量表達式
...
#elif 常量表達式
...
#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)定的海外服務器提供商?創(chuàng)新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧

當前題目:程序環(huán)境和預處理-創(chuàng)新互聯
當前路徑:http://bm7419.com/article22/cecjjc.html

成都網站建設公司_創(chuàng)新互聯,為您提供關鍵詞優(yōu)化、云服務器ChatGPT、外貿建站、網站改版、標簽優(yōu)化

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

綿陽服務器托管