C語言bool占用4個字節(jié)?匯編之下無秘密|帶你看extern
昨天群友發(fā)文詢問,為什么C語言里bool似乎占用4Byte,給bool賦值后,它后面的3個字節(jié) 內容也被修改了,并且她還強調代碼沒有經過編譯器優(yōu)化(-O0是關閉優(yōu)化的意思)。
群友很是細心,生成map文件檢查bool類型占用的空間,也確認是1字節(jié)。
我建議他“反匯編源碼,匯編之下無秘密”。
反匯編后確認給變量賦值的匯編指令是"STR",在arm架構下STR指令操作數(shù)占4Byte。
最終它找到原因是在extern變量時寫錯變量類型為int,以至于本應用STRB指令的地方誤用成STR。
extern寫時一時爽、排故火葬場。
編譯器才不管你原始變量定義成什么類型,extern讓他看到什么類型他就認為是什么。讀書時看老師的代碼,很疑惑為什么簡單返回變量值,沒任何邏輯和運算操作,卻要封裝成一個函數(shù)。
老師笑笑:“Too yong Too simple。”
源碼
他的源碼復現(xiàn)方式我寫在下面,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ā)的錯誤,就算生成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
匯編之下無秘密
arm-linux-objdump -S a.out > b.dis
被錯誤聲明成整型。
-
-
-
-
-
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語言并沒有對true和false特殊定義,而是直接定義成1和0,相當于 true和false都占用4byte。
思考:既然C語言根本沒有1bit的類型,那么它是怎么實現(xiàn)bool類型“邏輯判斷”的呢?
你可以像我上文那樣反匯編看看。再思考按照反匯編的運作方式,它會遇到什么坑?