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

看板C_and_CPP作者 (gowrite)時間6年前 (2017/09/06 23:38), 編輯推噓8(8012)
留言20則, 10人參與, 最新討論串1/1
開發平台(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 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.195.54.122 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1504712284.A.FD8.html

09/06 23:48, , 1F
關鍵字:alignment與padding
09/06 23:48, 1F

09/06 23:53, , 2F
code跟compiler都沒問題
09/06 23:53, 2F

09/07 00:15, , 3F
你想要很緊緻的話也可以加個keyword 讓他沒有padding
09/07 00:15, 3F

09/07 00:16, , 4F
主要是因為cpu 一次都抓很多個byte起來 所以compiler會
09/07 00:16, 4F

09/07 00:16, , 5F
加padding 細節你還是google一下有詳盡解說
09/07 00:16, 5F

09/07 06:23, , 7F
對齊,這樣存取資源比較有效率
09/07 06:23, 7F

09/07 07:48, , 8F
咦! 我還以為是int、char宣告順序的問題,記憶體大小是
09/07 07:48, 8F

09/07 07:48, , 9F
根據struct內依序宣告中,占用最大記憶體空間的變數為
09/07 07:48, 9F

09/07 07:48, , 10F
宣告標準
09/07 07:48, 10F

09/07 08:35, , 11F
不是,純粹就是alignment 又不是union XD
09/07 08:35, 11F

09/07 08:36, , 12F
不過這的確是沒經驗的人容易踩到雷的地方
09/07 08:36, 12F

09/07 12:31, , 13F
有大大清楚支援unaligned的ARMv7編譯器會如何處置嗎?
09/07 12:31, 13F

09/08 00:43, , 14F
對了!如果有使用class的virtual function也會有類
09/08 00:43, 14F

09/08 00:43, , 15F
似的結果
09/08 00:43, 15F

09/13 09:44, , 16F
padding 問題,如果不想要compiler幫你加,就要加keyword
09/13 09:44, 16F

09/13 09:45, , 17F
最常見的就是在網路封包上,定義好的結構不可以被更改
09/13 09:45, 17F

09/13 23:50, , 18F
protocol絕對要用bitfield或者自己做好padding
09/13 23:50, 18F

09/13 23:50, , 19F
不過自製padding很容易搞出相容性的人命就是 bitfield
09/13 23:50, 19F

09/13 23:50, , 20F
相對好做很多
09/13 23:50, 20F
文章代碼(AID): #1Pi1PS_O (C_and_CPP)