學習筆記 C 內聯函式

2021-10-25 05:19:09 字數 2868 閱讀 2152

對於乙個頻繁使用的短小函式,在c語言中應該用巨集定義實現,在c++中用inline實現。巨集定義與內聯函式的不同用法000。

在c語言中,寫一手漂亮的巨集定義是非常有必要的,方式出錯;提高**的移植性和可讀性等。尤其是一些常用或通用的功能函式或者**段,這些功能既可以寫成函式,也可以封裝為巨集定義。就功能性上來講,用巨集定義自然有函式無法比擬的優勢所在。

#define max(a,b) ((a)>(b)?(a):(b)) 

//乙個簡單的大小比較的巨集定義函式

但是如果用函式實現的話,你可能得先宣告,並且定義,尤其是對變數型別的侷限性上:

int

max(

int a ,

int b)

;//宣告

//定義

intmax

(int a,

int b)

比較明顯,巨集定義簡單又方便;同時,函式地呼叫會帶來額外的開銷,他需要開闢一片棧空間,記錄返回位址,函式返回還要釋放。這種開銷很明顯地會降低**效率,而且**量也會大大增加,而使用巨集定義則在**規模和速度方面都有優勢。其次就是變數型別上,在c++中因為有模板還可以實現多型別變數的比較,但是在上述**中僅僅支援int型別的變數進行比較。但巨集定義就有所不同,可以用於整形、長整型、單浮點型、雙浮點型以及其他一些可以用>操作符進行比較的變數型別,就是說,巨集定義是不需要考慮型別的。

在具體使用中,較多場合會因為使用巨集定義重新命名函式名以及定義一些變數。

#define malloc(n, type) \

((type *) malloc((n)* sizeof(type))

利用這個巨集,我們就可以簡單的為任何型別分配一段我們指定的空間大小,並返回指向這段空間的指標。

int

*ptr;

ptr =

malloc(5

,int);

//申請5int大小的空間

關於巨集定義還會有一些小問題,可能也會導致你使用上的錯誤,例如:

#define square_sum(x,y) x*x+y*y

#include

intmain()

上述**真實的呼叫是1+1*1+1+2*2=7,這一點需要注意,所以如果有需要的話,建議給變數小括號帶上。

屬性#define巨集

函式**長度

每次使用時,巨集**都被插入到程式中。除了非常小的巨集之外,程式的長度將大幅度增長。

函式**只出現於乙個地方:每次使用這個函式時,都呼叫那個地方的同乙份**

執行速度

更快存在函式呼叫、返回的額外開銷

操作符優先順序

巨集引數的求值是在所有周圍表示式的上下文環境裡,除非它們加上括號,否則鄰近操作符的優先順序可能產生不可預料的結果。

函式引數只在函式呼叫時求值一次,它的結果值傳遞給函式。表示式的求值結果更容易**。

引數求值

引數用於巨集定義時,每次都將重新求值,由於多次求值,具有***的引數可能會產生不可**的結果。

引數在函式呼叫前只求值一次,在函式中多次使用引數並不會導致多次求值過程,引數的***並不會造成任何特殊問題。

引數型別

巨集與型別無關,只要引數的操作是合法的,它可以用於任何引數型別。

函式的引數是與型別有關係的,如果引數的型別不同,就需要使用不同的函式,即使它們執行的任務是相同的。

在系統下,棧空間是有限的,加入頻繁大量的使用就會造成因棧空間不足所造成的程式出錯的問題,內聯函式的引入也是為了解決一些頻繁呼叫的小函式大量消耗棧空間的問題。

看乙個例子:

#include

//函式定義為inline即:內聯函式

inline

char

*dbtest

(int a)

intmain()

}

在這種情況時當在下表呼叫函式時,會變成(i%2>0)?"奇":"偶";避免了函式的重複呼叫對棧記憶體重複開闢所帶來的消耗;當然,inline函式不是在任何條件下都可以使用的,只有函式本身沒有呼叫本身並且函式不是複雜函式(當函式中存在while迴圈或swich語句時為複雜函式,但是不是複雜函式還要看編譯器對它的判斷)時,才可以使用;

注意點:

inline函式僅僅是乙個建議,對編譯器的建議,所以最後能否真正內聯,看編譯器的意思,它如果認為函式不複雜,能在呼叫點展開,就會真正內聯,並不是說宣告了內聯就會內聯,宣告內聯只是乙個建議而已.

其次,因為內聯函式要在呼叫點展開,所以編譯器必須隨處可見內聯函式的定義,要不然,就成了非內聯函式的呼叫了.所以,這要求每個呼叫了內聯函式的檔案都出現了該內聯函式的定義。因此,將內聯函式放在標頭檔案裡實現是合適的,省卻你為每個檔案實現一次的麻煩.而所以宣告跟定義要一致,其實是指,如果在每個檔案裡都實現一次該內聯函式的話,那麼,最好保證每個定義都是一樣的,否則,將會引起未定義的行為,即是說,如果不是每個檔案裡的定義都一樣,那麼,編譯器展開的是哪乙個,那要看具體的編譯器而定.所以,最好將內聯函式定義放在標頭檔案中.

而類中的成員函式預設都是內聯的,如果在類定義時就在類內給出函式,那當然最好;如果在類中未給出成員函式定義,而又想內聯該函式的話,那在類外要加上inline,否則就認為不是內聯的.

為了方便,將內聯函式直接宣告時就定義,放在標頭檔案中.這樣其它檔案包含了該標頭檔案,就在每個檔案都出現了內聯函式的定義.就可以內聯了.

參考文章:[c++] 用巨集定義乙個函式 - 推杯問盞 -

c 學習筆記 內聯函式(inline)

在c 中呼叫函式時,電腦要做很多事 呼叫前要先儲存暫存器,並在返回時恢復 而且還有實參到形參的傳值 如果乙個函式在原始碼中多次被呼叫,這樣就會很浪費計算機的資源,但是如果我們將這個函式宣告為內聯函式,就可不必有這樣的擔心了。例如這樣乙個函式 int max int x,int y return x ...

C 學習筆記(八) 內聯函式

內聯函式 內聯函式實際上並不是真正的函式,它比較像define巨集定義,它實際上就是將 段直接替換到呼叫函式的地方,從而實現時間的節約。使用 主要用在 較短的函式中,同時不能用在遞迴函式中。在函式最前面加上inline就是內聯函式了 inline函式的本質也是用空間換取時間的一種操作 例子程式 in...

學習筆記 內聯函式

1.什麼是內聯函式?內聯函式,從形式上看就是普通函式首部前新增了乙個inline,形式如下 inline 引數列表 語句 2.為什麼引進內聯函式?內聯函式與普通函式的區別在於,內聯函式的呼叫不會轉移程式控制權,而是在呼叫點處進行 內聯 展開函式體,類似於巨集展開 區別在於巨集展開是由預處理器負責,而...