來源:公眾號【魚鷹談單片機】
作者:魚鷹Osprey
ID :emOsprey
這周課上介紹斷言實現的時候,莫名其妙被斷言的真真假假搞暈了。
起因是看到一段關于判斷一段字符串的長度,使用了 ASSERT 方式,原文大概是這樣寫的:
#define AES256_KEY "0123456789ABCDEF0123456789ABCDEF" /* 必須等于 32 字節 */ #define AES256_IV "0123456789ABCDEF" /* 必須等于 16 字節 */ extern void Assert_Failed(uint8_t *func, uint32_t line); #define ASSERT(expr) ((expr) ? (void)0U : Assert_Failed((uint8_t *)__func__, __LINE__)) voidfunc() { ASSERT(sizeof(AES256_KEY) != 32); ASSERT(sizeof(AES256_IV) != 16); }
一開始總以為這種寫法沒問題,畢竟這么簡單,模擬調試的時候確實也不會報錯(打開了斷言情況下)。
為了課上測試一下靜態編譯報錯的效果,卻發現始終有些問題,不該報錯的時候報錯了。
#define STATIC_ASSERT(...) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(__VA_ARGS__)])]
為了方便,魚鷹直接用 MDK 測試了 sizeof 字符串的結果,發現確實也是16(0x10)
然后我就困在了這兩個前提上,STATIC_ASSERT 報錯始終有問題。
#define AES256_KEY "0123456789ABCDEF0123456789ABCDEF" /* 必須等于 32 字節 */ #define AES256_IV "0123456789ABCDEF" /* 必須等于 16 字節 */ extern void Assert_Failed(uint8_t *func, uint32_t line); #define ASSERT(expr) ((expr) ? (void)0U : Assert_Failed((uint8_t *)__func__, __LINE__)) #define STATIC_ASSERT(...) extern char (*_do_assert(void)) [sizeof(char[1 - 2*!(__VA_ARGS__)])] void func() { ASSERT(sizeof(AES256_KEY) != 32); ASSERT(sizeof(AES256_IV) != 16); STATIC_ASSERT(sizeof(AES256_IV)!=16); }
調試的時候,STATIC_ASSERT 報錯,但是 ASSERT不報錯。
這讓魚鷹百思不得其解,一開始以為兩個宏邏輯相反,不都是邏輯值為假時報錯。
但是通過分析宏發現,都是假的時候報錯。
那肯定哪里分析有問題了。
因為編譯器如果能得到結果為真,ASSERT可能無法形成代碼,即為空(void)0U。
因此魚鷹使用了一個變量作為中間值,強行讓編譯器生成斷言相關的代碼,才算是發現了問題。
void func() { uint32_tsize = sizeof(AES256_IV); ASSERT(sizeof(AES256_KEY) != 32); ASSERT(size!=16); STATIC_ASSERT(sizeof(AES256_IV) != 16); }
這個size 的值竟然是 17,而不是 16,難怪初始代碼不報錯,17 != 16,當然為真,當然不報錯。
但寫代碼的人是希望這個字符串的長度為始終是16(不包含null的情況下),而明顯代碼中使用sizeof 時計算了 null 的長度。
所以代碼應該這樣寫才對:
void func() { ASSERT(sizeof(AES256_KEY)==32); ASSERT(sizeof(AES256_IV)==16); STATIC_ASSERT(sizeof(AES256_IV)==16); }
但是又因為代碼的sizeof 會計算null,因此需要去除這個數:
void func() { ASSERT(sizeof(AES256_KEY) - 1==32); ASSERT(sizeof(AES256_IV) - 1==16); STATIC_ASSERT(sizeof(AES256_IV) - 1==16); }
這樣 STATIC_ASSERT 可以在編譯階段就可以判斷這個字符串的長度是否符合要求,多一個、少一個字符都不行。
這個坑你們遇到過嗎?
-
字符串
+關注
關注
1文章
578瀏覽量
20508 -
編譯器
+關注
關注
1文章
1623瀏覽量
49108 -
編譯
+關注
關注
0文章
657瀏覽量
32852
原文標題:被斷言罷了一道
文章出處:【微信號:emOsprey,微信公眾號:魚鷹談單片機】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論