標籤

網誌存檔

2009年10月16日 星期五

Define 和 inline

http://phorum.study-area.org/index.php?topic=56407.0

小弟最近在trace一些linux code, 看到了一些令我不解的程式碼...
有些程式碼之中使用
#define function(x) do{...}while(0)
有時又看到使用inline的function,
我一開始以為 #define do{...}while(0) 的寫法等於 inline
後來發現有人的程式裡#define 和 inline穿插使用,
這兩個除了在compile時的差異之外,
想請問各位學長, 在performance上是否有差異和影響, 為什麼要這樣寫?
已記錄
elleryq
區域板主
鑽研的研究生
*****
會員性別: 男
文章: 751



檢視個人資料 個人網站
« 回覆文章 #1 於: 2009-04-27 09:16 »

#define 在需要 local variable 的情況下,比較不適合使用
inline 的話,就會比較方便...

另外,
#define 在行數多的時候,比較不容易理解
inline 相對比較清楚一些,因為整個包在 function block 裡.
已記錄

lan your work, then work your plan.
我的首頁:http://blog.roodo.com/thinkingmore/
351899by http://counter.li.org
arfken
可愛的小學生
*
文章: 9



檢視個人資料
« 回覆文章 #2 於: 2009-06-03 13:58 »

#define 是 C 時代的產物。不具型別判斷。是單純的巨集。
邊際效應比較嚴重。但是,在微處裡器大家還是常用。

inline 是 C++ 時代的新產品。想保有function的封裝性,又不想付出function call的額外付出。
但是,在不同的編譯器可能會有不同的處理方式。
已記錄
kenduest
酷!學園 學長們
俺是博士!
*****
文章: 3007



檢視個人資料 個人網站
« 回覆文章 #3 於: 2009-06-03 15:11 »

小弟最近在trace一些linux code, 看到了一些令我不解的程式碼...
有些程式碼之中使用
#define function(x) do{...}while(0)
有時又看到使用inline的function,
我一開始以為 #define do{...}while(0) 的寫法等於 inline
後來發現有人的程式裡#define 和 inline穿插使用,
這兩個除了在compile時的差異之外,
想請問各位學長, 在performance上是否有差異和影響, 為什麼要這樣寫?

這樣寫是有特殊用途的,等等解釋。

首先 inline 只有 c++ 才有,linux kernel source 基本上不大可能使用 inline 方式語法,只能夠使用 define 這類 c 與 c++ 都可以支援方式。

define 的許多問題我想大家應該知道,常見像是:

程式碼:
#define sq(a) (a*a)

這表示自己次方,一般使用上沒問題,像是:

程式碼:
int answer = sq(5); // 答案是 25

但是這樣用就死了...

程式碼:
int answer = sq(5+1) // 答案不是 36 啊.....

因為實際上是 5+1 * 5+1 ==> 5+5+1 = 11

所以要改成:

程式碼:
#define sq(a) ((a)*(a))

在 inline 內這類問題都不會發生就是...

拉回來,至於你說的問題....

程式碼:
#define function(x) do{...}while(0)

這寫法也是有特殊的意義,記得應該是 linux kernel FAQ 有寫.

程式碼:
#define swap(x,y) { int tmp_n ; tmp_n = x ; x = y ; y = tmp_n; }

但是這樣使用遇到這種情況會有問題:

程式碼:
if ( x > y )
swap(x,y);
else
otherthing();

但是程式碼展開就會....

程式碼:
if ( x > y )
{ int tmp_n ; tmp_n = x ; x = y ; y = tmp_n; };
else
otherthing();

有無看到問題點?

程式碼:
if ( x > y ) {
int tmp_n ;
tmp_n = x
x = y
y = tmp_n;
}
; <---- 這邊多分號,慘了 ~~~~
else
otherthing();

這導致會編譯錯誤,因為 else 算是多出來的,已經不是與 else 配對的...

基於這個原因,所以才引入 function(x) do{...}while(0) 來解決

#define swap(a,b) do { int tmp_n ; tmp_n = x ; x = y ; y = tmp_n; } while(0)

那展開使用就是

程式碼:
if ( x > y )
do {
int tmp_n ;
tmp_n = x;
x = y;
y = tmp_n;
} while(0);
else
otherthing();

這樣就不會出包了....
« 最後編輯時間: 2009-06-03 15:21 由 kenduest » 已記錄

如果真的愛一個作業系統 怎能不害怕不再能使用它
而我們必須接受現實 於是長大了 寂寞就是沒有了機會再用它 比沒有電腦還要寂寞
而那些點亮我們生命的作業系統 就彷彿電影中發生在暹邏的故事
即使短暫使用也會刻骨銘心
To all the Linux that bring us to kernel.
elleryq
區域板主
鑽研的研究生
*****
會員性別: 男
文章: 751



檢視個人資料 個人網站
« 回覆文章 #4 於: 2009-06-04 09:41 »

我知道 do { } while(0) 是為了避掉問題,但我現在才知道是為了 ';'
長見識了,謝謝 kenduest 詳細的解說。