C語(yǔ)言bool占用4個(gè)字節(jié)?匯編之下無(wú)秘密|帶你看extern
昨天群友發(fā)文詢問(wèn),為什么C語(yǔ)言里bool似乎占用4Byte,給bool賦值后,它后面的3個(gè)字節(jié) 內(nèi)容也被修改了,并且她還強(qiáng)調(diào)代碼沒(méi)有經(jīng)過(guò)編譯器優(yōu)化(-O0是關(guān)閉優(yōu)化的意思)。
群友很是細(xì)心,生成map文件檢查bool類型占用的空間,也確認(rèn)是1字節(jié)。
我建議他“反匯編源碼,匯編之下無(wú)秘密”。
反匯編后確認(rèn)給變量賦值的匯編指令是"STR",在arm架構(gòu)下STR指令操作數(shù)占4Byte。
最終它找到原因是在extern變量時(shí)寫(xiě)錯(cuò)變量類型為int,以至于本應(yīng)用STRB指令的地方誤用成STR。
extern寫(xiě)時(shí)一時(shí)爽、排故火葬場(chǎng)。
編譯器才不管你原始變量定義成什么類型,extern讓他看到什么類型他就認(rèn)為是什么。讀書(shū)時(shí)看老師的代碼,很疑惑為什么簡(jiǎn)單返回變量值,沒(méi)任何邏輯和運(yùn)算操作,卻要封裝成一個(gè)函數(shù)。
老師笑笑:“Too yong Too simple?!?/span>
源碼
他的源碼復(fù)現(xiàn)方式我寫(xiě)在下面,bool類型是C99引入的。
// bool.c ------------------------------------- bool b_a = true;char c_a = 'a';char c_b = 'b';char c_c = 'c'; void fun_print() { printf("%2x %2x %2x %2x\r\n", b_a, c_a, c_b, c_c);} // main.c ------------------------------------- extern int b_a; // 這里不一樣extern void fun_print(); void main(){ printf("原始值:"); fun_print(); b_a = false; printf("修改后:"); fun_print();}
arm-linux-gcc *.c ./a.out 原始值: 1 61 62 63修改后: 0 0 0 0
extern引發(fā)的錯(cuò)誤,就算生成map文件也是看不出的,下面能看到b_a僅占用1Byte, 后面緊跟著c_a變量
arm-linux-gcc *.c -Wl,-Map=gcc.map cat gcc.map | grep b_a -C 3 0x00011028 0x4 /tmp/ccmJQHpj.o 0x00011028 b_a 0x00011029 c_a 0x0001102a c_b 0x0001102b c_c
匯編之下無(wú)秘密
arm-linux-objdump -S a.out > b.dis
被錯(cuò)誤聲明成整型。
-
-
-
-
-
extern int b_a; b_a = false; 843c: e59f3024 ldr r3, [pc, 8440: e3a02000 mov r2, 8444: e5832000 str r2, [r3]
正確聲明成布爾類型。
-
-
-
-
-
extern bool b_a; b_a = false; 843c: e59f3024 ldr r3, [pc, 8440: e3a02000 mov r2, 8444: e5c32000 strb r2, [r3]
思考
查閱stdbool.h源碼,C語(yǔ)言并沒(méi)有對(duì)true和false特殊定義,而是直接定義成1和0,相當(dāng)于 true和false都占用4byte。
思考:既然C語(yǔ)言根本沒(méi)有1bit的類型,那么它是怎么實(shí)現(xiàn)bool類型“邏輯判斷”的呢?
你可以像我上文那樣反匯編看看。再思考按照反匯編的運(yùn)作方式,它會(huì)遇到什么坑?