[問題] 記憶體配置的奇怪現象

作者: gowrite (gowrite)   2017-09-06 23:38:01
開發平台(Platform): (Ex: Win10, Linux, ...)
windows 8
編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)
gcc ( IDE == code::blocks )
額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
n/a
問題(Question):
最近在學習結構 struct,順便觀察所配置的記憶體數量,發現一個奇怪的現象
如果我定義一個結構 s1,裡面設定一個字元陣列 chArr
struct s1{
char chArr[ N ]
}
chArr 的長度我隨便設定 N
因為我知道 char 所佔的記憶體就是 1 byte ,
所以 printf( "%d" , sizeof(a) ); 數量就是 N,
到這裡都沒問題。
可是當我另外定義了一個結構 s2,裡面設定了一個字元陣列 chArr 跟 int num,
這時候,字元陣列的 chArr 的記憶體分配就會以 4 bytes 的倍數來跳
struct s2{
char ch[0];
int num;
};
int main(){
struct s2 abc;
printf("size of abc == %d" , sizeof(abc));
}
照理說如果有宣告一個結構變數 abc,那 abc 所佔的記憶體量應該是
char [n] + int
n bytes + 4 bytes == (n+4) bytes
當我設定
ch[0] == printf 出來是 abc 的記憶體用量是 4 (正確)
( 0byte + 4bytes == 4bytes )
可是當我增加字元陣列的 size 之後
ch[1] == printf 出來是 abc 的記憶體用量是 8 (怪) (預期是 5)
ch[2] == printf 出來是 abc 的記憶體用量是 8 (怪) (預期是 6)
ch[3] == printf 出來是 abc 的記憶體用量是 8 (怪) (預期是 7)
ch[4] == printf 出來是 abc 的記憶體用量是 8 (正確)
ch[5] == printf 出來是 abc 的記憶體用量是 12 (怪) (預期是 9)
ch[6] == printf 出來是 abc 的記憶體用量是 12 (怪) (預期是 10)
ch[7] == printf 出來是 abc 的記憶體用量是 12 (怪) (預期是 11)
ch[8] == printf 出來是 abc 的記憶體用量是 12 (正確)
ch[9] == printf 出來是 abc 的記憶體用量是 16 (怪) (預期是 13)
ch[10] == printf 出來是 abc 的記憶體用量是 16 (怪) (預期是 14)
ch[11] == printf 出來是 abc 的記憶體用量是 16 (怪) (預期是 15)
ch[12] == printf 出來是 abc 的記憶體用量是 16 (正確)
.
.
.
這個情況只有在結構有加入 int 的變數時會發生,
如果只有一個字元變數或兩個字元變數都不會發生,
其他型態變數,目前還沒發現,
想問是我哪邊 code 有寫錯嗎?
還是 compilor 的問題??
謝謝。
餵入的資料(Input):
如上
預期的正確結果(Expected Output):
分析結果如上
錯誤結果(Wrong Output):
記憶體分配有違反 char type 1 byte 狀況
分析結果如上
程式碼(Code):(請善用置底文網頁, 記得排版)
struct s2{
char ch[0];
int num;
};
int main(){
struct s2 abc;
printf("size of abc == %d" , sizeof(abc));
}
補充說明(Supplement):
n/a
作者: Caesar08 (Caesar)   2017-09-06 23:48:00
關鍵字:alignment與padding
作者: grayStone (灰色石頭)   2017-09-06 23:53:00
code跟compiler都沒問題
作者: steve1012 (steve)   2017-09-07 00:15:00
你想要很緊緻的話也可以加個keyword 讓他沒有padding主要是因為cpu 一次都抓很多個byte起來 所以compiler會加padding 細節你還是google一下有詳盡解說
作者: RouterHsieh (醉臥美人膝,醒掌天下權)   2017-09-07 03:29:00
作者: b0920075 (Void)   2017-09-07 06:23:00
對齊,這樣存取資源比較有效率
作者: s4300026 (s4300026)   2017-09-07 07:48:00
咦! 我還以為是int、char宣告順序的問題,記憶體大小是根據struct內依序宣告中,占用最大記憶體空間的變數為宣告標準
作者: Killercat (殺人貓™)   2017-09-07 08:35:00
不是,純粹就是alignment 又不是union XD不過這的確是沒經驗的人容易踩到雷的地方
作者: TianBonBon (田蹦蹦)   2017-09-07 12:31:00
有大大清楚支援unaligned的ARMv7編譯器會如何處置嗎?
作者: rbufghj9713 (我只是來潛水)   2017-09-08 00:43:00
對了!如果有使用class的virtual function也會有類似的結果
作者: dou0228 (7777)   2017-09-13 09:44:00
padding 問題,如果不想要compiler幫你加,就要加keyword最常見的就是在網路封包上,定義好的結構不可以被更改
作者: Killercat (殺人貓™)   2017-09-13 23:50:00
protocol絕對要用bitfield或者自己做好padding不過自製padding很容易搞出相容性的人命就是 bitfield相對好做很多

Links booklink

Contact Us: admin [ a t ] ucptt.com