• 正文
    • 開門見山
    • 語法解析
    • 應(yīng)用場景
    • 拓展
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

【LeafC】C語言之宏魔法1:BUILD_BUG_ON

01/20 09:03
1893
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

開門見山

在編寫程序時,我們總是希望能夠盡早地發(fā)現(xiàn)問題,而在編碼的不同階段,發(fā)現(xiàn)問題的手段也因時而異。

對C語言開發(fā)的項目來說,BUILD_BUG_ON就是這么一個可以在編譯期間檢查代碼靜態(tài)約束的宏。

#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

BUILD_BUG_ON的原理如下:

當(dāng)condition為false(0)時,由于1-2*!!(condition)為 1,宏被展開為sizeof(char[1]),這是合法語句,并且編譯后不產(chǎn)生額外代碼;

當(dāng)condition為true(非0)時,由于1-2*!!(condition)為 -1,宏被展開為sizeof(char[-1]),而這是非法語句,編譯報錯。

condition代表的是非預(yù)期的情況,如果這種非預(yù)期的情況真的出現(xiàn)了,那么問題將在編譯期就被發(fā)現(xiàn)。

語法解析

細(xì)心的朋友可能會問:sizeof(char[1])這條語句是什么意思呢?

這個表達(dá)式中,char[1]其實是一個類型,sizeof(char[1])就是該類型(即長度為1的char型數(shù)組)所占內(nèi)存大小。

欸?char[1]居然是類型,那C語言是不是可以用這種方式定義數(shù)組呢:

char[2] arr = { 1, 2 };

答案是:不可以,這不符合C語言的語法。正確寫法是我們熟悉的下面這種:

char arr[2] = { 1, 2 };

事實上,如果要用typedef定義一個長度為2的char型數(shù)組類型,應(yīng)該這么做:

// 錯誤寫法:
typedef char[2] char_2;
// 正確寫法:
typedef char char_2[2];
char_2 arr = { 1, 2 };

這是由于C語言并不是一個完全的前綴類型聲明語言,有些類型如果要做到前綴類型聲明,需要用typedef這個關(guān)鍵字來為類型定義一個新名字。比如函數(shù)類型:

// 定義函數(shù)
void test_func(int a, char b) { … }
// 不使用typedef
void (*func)(int, char) = test_func;
// 使用typedef
typedef void (*func_t)(int, char);
func_t func = test_func;

同理,sizeof運算符也可以計算其占用內(nèi)存大?。?/p>

// 以下2種寫法是等價的,64位系統(tǒng)中結(jié)果為8
sizeof(void (*)(int, char))
sizeof(func_t)

應(yīng)用場景

BUILD_BUG_ON常用于判斷編譯時確定,且無法在預(yù)編譯時確定的條件表達(dá)式,使用時將其放在需要判斷條件約束的相關(guān)函數(shù)內(nèi)即可。

使用的場景例如:結(jié)構(gòu)體類型的大小是否滿足某種條件,或者兩個枚舉常量的映射關(guān)系是否符合要求。

拓展

除了BUILD_BUG_ON,還有一些實用的宏同樣能在編譯期檢查代碼的靜態(tài)約束:

#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))

原理如下:

這2個宏利用了C語言結(jié)構(gòu)體位字段長度不能為負(fù)數(shù)的性質(zhì),分別實現(xiàn)宏參數(shù)非0報錯(預(yù)期為0)和非NULL報錯(預(yù)期為NULL)。

在linux 3.19內(nèi)核/include/linux/bug.h中,還有個BUILD_BUG_ON宏的升級版BUILD_BUG_ON_MSG(cond, msg),這個宏額外多了一個msg參數(shù),用來設(shè)定不滿足條件時編譯錯誤所打印的信息,不過該宏是通過gcc的拓展特性實現(xiàn),并不通用。

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄