c語言再學習之巨集與函式

2021-07-26 05:53:55 字數 2383 閱讀 8994

巨集概念:

c++巨集定義將乙個

識別符號定義為乙個字串,源程式

中的該識別符號均以指定的字串來代替。

巨集書寫形式:

#define 《巨集名》(《參數列》) 《巨集體》

巨集與函式的區別:

時間上考慮:

1:巨集只佔編譯時間,函式呼叫則占用執行時間(分配單元,儲存現場,值傳遞,返回),每次執行都要載入,所以執行相對巨集會較慢。

2:使用巨集次數多時,巨集展開後源程式很長,因為每展開一次都使程式增長,但是執行起來比較快一點(這也不是絕對的,當有很多巨集展開,目標檔案很大,執行的時候執行時系統換頁頻繁,效率就會低下)。而函式呼叫不使源程式變長。

安全性考慮:

3:函式呼叫時,先求出實參表示式的值,然後帶入形參。而使用帶參的巨集只是進行簡單的字元替換。

4:函式呼叫是在程式執行時處理的,分配臨時的記憶體單元;而巨集展開則是在編譯時進行的,在展開時並不分配記憶體單元,不進行值的傳遞處理,也沒有「返回值」的概念。

5:對函式中的實參和形參都要定義型別,二者的型別要求一致,如不一致,應進行型別轉換;而巨集不存在型別問題,巨集名無型別,它的引數也無型別,只是乙個符號代表,展開時帶入指定的字元即可。巨集定義時,字串可以是任何型別的資料。

6:巨集的定義很容易產生二義性,如:定義#define s(a) (a)*(a),**

s(a++),巨集展開變成(a++)*(a++)這個大家都知道,在不同編譯環境下會有不同結果。

結構性考慮:
7:呼叫函式只可得到乙個返回值,且有返回型別,而巨集沒有返回值和返回型別,但是用巨集可以設法得到幾個結果。

8:函式體內有bug,可以在函式體內打斷點除錯。如果巨集體內有bug,那麼在執行的時候是不能對巨集除錯的,即不能深入到巨集內部。

9:c++中巨集不能訪問物件的私有成員,但是成員函式就可以。

還有⼀些任務根本⽆法使⽤函式實現。讓我們仔細觀察下⾯的**: #define malloc( n, type) \ ( ( type *) malloc ( (n) * sizeof( type ) ) ) 

int *pi = malloc( 25, int );這個巨集的第⼆個引數是⼀種型別,它⽆法作為函式引數進⾏傳遞。這個巨集替換完成之後:int *pi = ( ( int *) malloc ( (25) * sizeof( int ) ) );

帶副作⽤的巨集引數

當巨集引數在巨集定義中出現次數超過⼀次時,如果這個引數具有副作⽤,那麼當你使⽤這個巨集時就可能出現危險,導致不可預料的結果。

副作⽤就是在表示式求值時出現的永久性效果。例如,下⾯表示式 x + 1;可以執⾏⼏百次,他每次獲得結果都是⼀樣的,這個表示式不具有副作⽤。

但是 x ++;就有副作⽤:它增加x的值。當這個表示式下⼀次執⾏時,他將產⽣⼀個不同的結果。max巨集可以證明具有副作⽤的引數所引起的問題。

這⾥較⼩的值計算了⼀次,但是較⼤的值卻計算了兩次。副作⽤並不僅限於修改變數的值,getchar()也會產⽣副作⽤。

調⽤這個函式將」消耗「

輸⼊的⼀個字元。

內聯函式

內聯函式(inline)和巨集的區別(內聯函式的優點)

內聯函式和巨集的區別在於,巨集是由預處理器對巨集進行替代,而內聯函式是通過編譯器控制來實現的。而且內聯函式是真正的函式,只是在需要用到的時候,內聯函式像巨集一樣的展開,所以取消了函式的引數壓棧,減少了呼叫的開銷。你可以象呼叫函式一樣來呼叫內聯函式,而不必擔心會產生於處理巨集的一些問題。

內聯函式也有一定的侷限性。

就是函式中的執行**不能太多了,如果,內聯函式的函式體過大,一般的編譯器會放棄內聯方式,而採用普通的方式呼叫函式。這樣,內聯函式就和普通函式執行效率一樣了。

如何選擇使用巨集還是函式:

以下情況可以選擇巨集,其他情況最好選用函式

1: 一般來說,用巨集來代表簡短的表示式比較合適。

2: 在考慮效率的時候,可以考慮使用巨集,或者內聯函式。

3:在標頭檔案保護(防止重複包含編譯),條件編譯中的#ifdef,#if defined以及assert的實現。

C語言再學習 函式

一 函式概述 1 首先什麼是函式?函式是用於完成特定任務的程式 的自包含單元。2 為什麼使用函式?第 一 函式的使用可以身故重複 的編寫。第 二 函式使得程式更加模組化,有利於程式的閱讀修改和完善。3 main函式原型 int main int argc,char argv,char envp 第乙...

C語言再學習 宣告與定義

什麼是定義?什麼是宣告?它們有何區別?舉個例子 a int i b extern int i 關於 extern,後面解釋 哪個是定義?哪個是宣告?或者都是定義或者都是宣告?我所教過的學生幾乎沒有一 人能回答上這個問題。這個十分重要的概念在大學裡從來沒有被提起過!什麼是定義 所謂的定義就是 編譯器 ...

c 再學習(函式指標與lamba)

什麼是函式指標?int cmp int a,int b 叫做捕獲說明符,表示乙個lambda表示式的開始。接下來是引數列表,即這個匿名的lambda函式的引數,return type表示返回型別,如果沒有返回型別,則可以省略這部分。想知道為什麼返回型別可以這麼表示,這涉及到c 11的另一特性,參見自...