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