|
從min&max一窺linux設(shè)計(jì)
好吧,我承認(rèn)我標(biāo)題黨了。但是我仍然建議你能夠繼續(xù)往下讀,最多花上一分鐘時(shí)間。
當(dāng)然,如果能夠浪費(fèi)你十分鐘以上,我的目的便達(dá)到了,而你也會(huì)有不一樣的體會(huì)。 問題:你會(huì)怎樣實(shí)現(xiàn)min & max這兩個(gè)函數(shù)呢?
我想大多數(shù)人的做法無非三種:1)定義宏;2)定義函數(shù); 3)定義inline函數(shù)。
對(duì)于第二種方法,不用多說,功能如此單一的函數(shù)效率會(huì)有折扣;對(duì)于第三種方法,inline是在較新的C99中引入的。其實(shí)我是在找理由,我太懶了,不想討論第二種和第三種,也是在掩飾現(xiàn)代編譯器強(qiáng)悍的優(yōu)化能力。也許,編譯器自動(dòng)為你把小函數(shù)優(yōu)化成內(nèi)聯(lián)了呢。OK,我們這里的主題是關(guān)于宏定義的,和其他無關(guān)。請(qǐng)看(下文都以min為例):
www.2cto.com
1
#define min(X,Y) ((X) < (Y) ? (X) : (Y))
這是一般的做法,對(duì)每個(gè)符號(hào)都還添加了括號(hào)處理,是比較讓人滿意的了。會(huì)有什么問題呢,繼續(xù)請(qǐng)看:
1
int x = 1, y = 2;
2
printf("min=%d/n", min(x++, y++)); //輸出min=2
3
printf("x = %d, y = %d/n", x, y); //輸出x=3, y=3
問題出現(xiàn)了,我們?cè)绢A(yù)期執(zhí)行min操作后,x為2,y為3。到底發(fā)生了什么呢,讓我們對(duì)宏進(jìn)行展開:
1
((x++) < (y++) ? (x++) : (y++))
看出來了嗎?問題就出在這里,x++被執(zhí)行了兩次。讓我們看看偉大的linux內(nèi)核是怎么解決這個(gè)問題的吧。
01
//include/linux/kernel.h
02
03
#define min(x,y) ({ /
04
typeof(x) _x = (x); /
05
typeof(y) _y = (y); /
06
(void) (&_x == &_y); /
07
_x < _y ? _x : _y; })
08
09
#define max(x,y) ({ /
10
typeof(x) _x = (x); /
11
typeof(y) _y = (y); /
12 www.2cto.com
(void) (&_x == &_y); /
13
_x > _y ? _x : _y; })
我在這里進(jìn)行簡(jiǎn)單的解釋:
1)typeof(X)的用途:得到X的類型信息。比如typeof(10) 為int, double f = 1.0; typeof(f)為double。
2)({})的用途:一句話,({和})之間可以有很多表達(dá)式,它的值為最后一個(gè)表達(dá)式的值。
3)(void) (&_x == &_y);這一句的作用是對(duì)_x和_y的類型判斷是否一樣。如果是不同的類型,編譯器會(huì)給出警告信息。
說白了,上述宏定義就是先引入和x及y同樣類型的兩個(gè)臨時(shí)變量,然后對(duì)臨時(shí)變量進(jìn)行求最大值或者最小值。
|
|
|