linux源碼中的BUILD_BUG_ON_ZERO(e)宏--編譯時(shí)斷言

本系列文章主要寫我在閱讀Linux內(nèi)核過程中,關(guān)注的比較難以理解但又設(shè)計(jì)巧妙的代碼片段(不關(guān)注OS的各個(gè)模塊的設(shè)計(jì)思想,此部分我準(zhǔn)備寫在“深入理解Linux Kernel”系列文章中),一來通過內(nèi)核代碼復(fù)習(xí)一下C語言及匯編語言的語法,二來學(xué)習(xí)內(nèi)核開發(fā)大牛們書寫代碼的風(fēng)格及思路。
在內(nèi)核文件include/linux/bug.h
中,有下面兩行的宏定義:
分析第一個(gè),它表示的是:檢查表達(dá)式e是否為0,為0編譯通過且返回0;如果不為0,則編譯不通過。
可能從這個(gè)宏的名字上看可能容易理解錯(cuò),或者改為“BUILD_BUG_OR_ZERO”更好,關(guān)于這個(gè)的討論有人也提交這個(gè)patch,但未能被社區(qū)接受。
我們且不管這個(gè)宏定義名字怎樣,來逐步分析一下這個(gè)宏是如何來實(shí)現(xiàn)的:
sizeof(struct { int : –!!(e); } ))
(e)
: 表達(dá)式e的聲明!!(e)
: 對e的結(jié)果進(jìn)行兩次求非。即如果e開始是0的話,結(jié)果就是0;如果e不為0,則結(jié)果為1。–!!(e)
: 再乘以-1。如果第2步結(jié)果為0,則仍為0;否則結(jié)果為-1。struct { int : –!!(0); }
?-->?struct { int : 0; }
: 如果e的結(jié)果為0,則我們聲明一個(gè)結(jié)構(gòu)體擁有一個(gè)int型的數(shù)據(jù)域,并且規(guī)定它所占的位的個(gè)數(shù)為0。這沒有任何問題,我們認(rèn)為一切正常。struct { int : –!!(1); }
?-->?struct { int : –1; }
: 如果e的結(jié)果非0,結(jié)構(gòu)體的int型數(shù)據(jù)域的位域?qū)⒆優(yōu)橐粋€(gè)負(fù)數(shù),將位域聲明為負(fù)數(shù)這是一個(gè)語法的錯(cuò)誤。現(xiàn)在要么結(jié)果為聲明了一個(gè)位域?yàn)?的結(jié)構(gòu)體,要么出現(xiàn)位域?yàn)樨?fù)數(shù)編譯出錯(cuò);如果能正確編譯,然后我們對該結(jié)構(gòu)體進(jìn)行sizeof操作,得到一個(gè)類型為size_t的結(jié)果,值為0。
再總結(jié)一下,BUILD_BUG_ON_ZERO(e)表示的就是若表達(dá)式e結(jié)果為0,則編譯通過,該宏的值也為0;若表達(dá)式e的結(jié)果不為0,則編譯不通過。
這會(huì)讓人聯(lián)想到C語言中assert
宏的用法:
void assert(int expression);
如果參數(shù)expression計(jì)算的結(jié)果為0,它先向stderr打印一條出錯(cuò)信息,然后通過調(diào)用abort來終止程序運(yùn)行;否則斷言成立,繼續(xù)執(zhí)行。
我們討論的宏與assert本質(zhì)區(qū)別在于,我們的宏在編譯時(shí)進(jìn)行測試,而assert宏是在運(yùn)行時(shí)測試。
我們希望能盡早地捕獲到我們編譯時(shí)的錯(cuò)誤,而不是推遲到運(yùn)行時(shí)。
我管這種宏用法叫做“編譯時(shí)斷言”,assert為“運(yùn)行時(shí)斷言”。
理解了上面之后,再來看看第二個(gè)BUILD_BUG_ON_NULL(e)
宏,與第一個(gè)類似,
用來在編譯時(shí)斷言e是否為NULL,若是這個(gè)宏返回(void *)0 (即NULL,與第一個(gè)宏的區(qū)別);
不為NULL時(shí)編譯出錯(cuò)。
除了上面的兩個(gè)編譯時(shí)斷言之外,include/linux/bug.h
文件中還有另幾個(gè)大家可以思考表示何意,如:
含義可以參考文件中宏定義的注釋說明。
-------------------------------------完--------------------------------
參考資料:
http://blog.csdn.net/jiyucn/article/details/862085?C語言中關(guān)于結(jié)構(gòu)體位域的詳細(xì)說明
http://blog.csdn.net/jiyucn/article/details/862062?C語言中sizeof相關(guān)問題
http://www.cplusplus.com/reference/cassert/assert/?assert用法說明
http://stackoverflow.com/questions/9229601/what-is-in-c-code?問題及解答均來源于Stackoverflow