[問題] sizeof struct 大小很奇怪

看板C_and_CPP作者時間10年前 (2013/10/16 21:39), 編輯推噓1(1035)
留言36則, 6人參與, 最新討論串1/2 (看更多)
大家好: 我想問關於struct的問題 最近無聊發現一個問題,後來有上網查還是一知半解 請版上先進不吝指教 如下 struct a{ char x; int y; short z; }; 結果去印sizeof(struct a)是12 而 struct b{ char x; short y; int z; }; 印出sizeof(struct b)是8 第一個我可以了解 0: x p p p 4: y y y y 8: z z p p 但是就第二個來講 我以為也會是12 但是卻是8 0: x p p p 4: y y p p 8: z z z z 但是卻好像不是這樣? 難道是? 0: x p y y 4: z z z z 這樣就很怪了阿 網路上查說這叫做對齊 主要目的是 "抓資料時可以一次抓" 網路上舉例 若一個int從位置6開始放 放在 6 7 8 9 非似的倍數就要抓兩次 可是,如果是這樣那應該都會對齊四吧? 為什麼第二種方式會對齊 2呢? 假設機器是32bit的話,怎麼想也是對齊4吧? struct x{ char a; char b; short c; } 這卻會是 0: a b c c 為啥不是 0: a x x x 4: b x x x 8: c c x x 這樣呢? 感謝! -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.136.182.93

10/16 21:43, , 1F
因為是對齊阿. 不要有人跨過邊界就可以了.
10/16 21:43, 1F

10/16 21:45, , 2F
每種資料型態的對齊不同
10/16 21:45, 2F

10/16 21:46, , 3F
x86一般char隨便放,short對齊2 int對齊4
10/16 21:46, 3F

10/16 21:47, , 4F
c++11有alignof(TYPE)可以看到底是多少
10/16 21:47, 4F

10/16 21:54, , 5F
為什麼不是對齊4阿 ?
10/16 21:54, 5F

10/16 22:07, , 6F
假設對齊 4 最快, 還要考慮空間浪費的問題.
10/16 22:07, 6F

10/16 22:25, , 7F
alignment對C語言來說不是implementation-defined的嗎@@
10/16 22:25, 7F

10/16 22:27, , 8F
跪求解析 >"<
10/16 22:27, 8F

10/16 22:36, , 9F
其實我比較想知道對齊2、4的理念是甚麼
10/16 22:36, 9F

10/16 22:37, , 10F
為什麼編譯氣會這樣翻? @@
10/16 22:37, 10F

10/16 22:42, , 11F
強迫對齊 4 你 x 會很多阿. 每個 char 只實際使用到 1/4 空間
10/16 22:42, 11F

10/16 22:43, , 12F
同理 short 本身如果只佔 2, 那對齊 4 只使用到 1/2 空間
10/16 22:43, 12F

10/16 22:45, , 13F
好複雜...
10/16 22:45, 13F

10/16 22:45, , 14F
那完全不對齊呢? 不是更省空間嗎 @@
10/16 22:45, 14F

10/16 22:46, , 15F
是阿. 但是假設對齊 4 效率最高的話, 效率就被犧牲了
10/16 22:46, 15F

10/16 22:47, , 16F
再根據資料型態 直接讀出對應的BYTE樹好像比較好@@
10/16 22:47, 16F

10/16 22:47, , 17F
這是個 trade-off, 所以是實作相依
10/16 22:47, 17F
那如果都不對齊的話 如 char a; short b; int c; a b b c c c c 再根據定義好的資料型態所對應的byte數 去讀資料,似乎又省空間又快? ※ 編輯: kumusou 來自: 220.136.182.93 (10/16 22:49)

10/16 22:48, , 18F
如果今天我們 short 是對齊 3, 那有些 short 會跨過 4 的邊界
10/16 22:48, 18F

10/16 22:48, , 19F
你 '可能' 要讀兩次才能讀到一個 short
10/16 22:48, 19F

10/16 22:49, , 20F
此外讀進 4 個 bytes 要取出其中任意個 bytes 要花時間
10/16 22:49, 20F

10/16 22:50, , 21F
以上都假設我們一次讀 4 個 bytes, 然後對齊 4 最快的情況
10/16 22:50, 21F

10/16 22:50, , 22F
你的例子我們要讀 c 的時候, 要讀兩次|a b b c| c c c x|
10/16 22:50, 22F

10/16 22:51, , 23F
然後還要把其中一個跟另外三個重新組起來 要解開重組
10/16 22:51, 23F

10/16 22:51, , 24F
假設硬體不支援的話就會很沒效率
10/16 22:51, 24F
為啥要你要把他四個一組阿? 假設 a b b c c c c 0 1 2 3 4 5 6 他可以直接在位置3直接抓sizeof(int)出來就是c了不是嗎? ※ 編輯: kumusou 來自: 220.136.182.93 (10/16 22:53)

10/16 22:55, , 25F
所以你為什麼說 32-bit 要對齊 4 ?
10/16 22:55, 25F
其實我是想 如果| a b b c | c c c p | c要讀兩次,所以要對齊四 i.e. | a p p p | b b p p | c c c c | 都抓一次就好 但是如果對齊二的話 i.e. | a p b b | c c c c | c讀一次 但他怎麼讀b啊? 我問題點比較像是這邊? (也是讀一次嗎?) ※ 編輯: kumusou 來自: 220.136.182.93 (10/16 22:59)

10/16 22:56, , 26F
那你的問題是我們為什麼需要對齊嗎 XD
10/16 22:56, 26F

10/16 23:00, , 27F
他就把 | a p b b | 抓過來然後拿後面兩個 bytes 就好~
10/16 23:00, 27F

10/16 23:01, , 28F
他怎麼知道b是後面兩個byte啊?
10/16 23:01, 28F

10/16 23:02, , 29F
其實你可以嘗試把你提出來有不同sizeof值的struct,寫一
10/16 23:02, 29F

10/16 23:02, , 30F
kumusou: 那他怎麼知道 c 是後面那一組阿. 這是一樣的問題
10/16 23:02, 30F

10/16 23:03, , 31F
段小程式,然後看compiler產生的assembly是怎麼樣存取其
10/16 23:03, 31F
那我說一下我現在的理解喔 因為讀資料幾乎都是以記憶體4的倍數在讀 | a p b b | c c c c | 0 1 2 3 4 5 6 7 所以就算知道b的記憶體位置是從2開始 他一次還是會先讀到0起始的4bytes 在解析出b 這樣對嗎? ※ 編輯: kumusou 來自: 220.136.182.93 (10/16 23:06)

10/16 23:04, , 32F
中struct裡的field(member)的,就可以知道apbb的b怎麼樣
10/16 23:04, 32F

10/16 23:04, , 33F
被讀出來的.
10/16 23:04, 33F

10/16 23:05, , 34F
其實你的問題也牽涉到計算機硬體呀!不然不用對齊不是更
10/16 23:05, 34F

10/16 23:06, , 35F
省空間嗎?所以建議要想一下(或問一下)為什麼會這樣...
10/16 23:06, 35F

10/16 23:07, , 36F
"記憶體4的倍數在讀"->這是因硬體而如此的!
10/16 23:07, 36F
文章代碼(AID): #1INfSaCv (C_and_CPP)
文章代碼(AID): #1INfSaCv (C_and_CPP)