[問題] union + struct + bitfield的問題

看板C_and_CPP (C/C++)作者 (薩哈拉雅)時間14年前 (2012/06/13 16:10), 編輯推噓5(5062)
留言67則, 9人參與, 最新討論串1/3 (看更多)
開發平台(Platform): (Ex: VC++, GCC, Linux, ...) freebsd 8.0 + gcc4.2.1 , run in winxp + virtualBox 在網路閒逛 看到兩個非常奇怪的問題, 如下: [case1] 請問以下的union大小為多少呢??? union A { struct { unsinged int p1:4; unsigned int p2:2; unsigned int p3:4; unsigned int p4:6; } } 經過測試結果是 4Bytes!!! 我想的是bitfields 總共16bits = 2 Bytes, 所以應該為 2 Bytes才對阿 請問這邊是哪裡想錯了呢?? 又這邊有一般的規則嗎??? [case2] union A { struct { unsinged int p1:4; unsigned int p2:2; unsigned int p3:4; unsigned int p4:6; } unsigned int kk; } union A obj = {3,2,4,5}; printf("value of kk: %u\n", obj.kk); 直接跑的結果是:316971043 bit pattern: 10111111 10111111 00010101 00100011 思考: p1 p2 p3 p4 0011 10 0100 000101 |<- 8 bits ->||<- 8bits->| 以bytes為單位不管以big-endia or little endian寫入,都跟跑出來的結果差很多 但是呢 若是以bit-fields為單位以little endian順序寫入, 則結果的bit pattern 後半段符合這個寫入結果.......(bit pattern前半段則是怎麼想都湊不出答案 @_@||) 一樣都是想不透...請各方好手指點迷津 這邊是不是我想錯了, 用錯方法或是哪邊有規則可以推導類似的問題呢??? 感謝大家!! -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.43.207.162 ※ 編輯: rifiz 來自: 114.43.207.162 (06/13 16:12)

06/13 16:33, , 1F
unsigned int --> unsigned short
06/13 16:33, 1F

06/13 17:09, , 2F
kk改成unsigned short也是4Bytes......XD
06/13 17:09, 2F

06/13 17:09, , 3F
印象中bit-field如何實作depend on compiler
06/13 17:09, 3F

06/13 17:10, , 4F
所以計較這個大小沒什麼意義 只能去猜compiler會以
06/13 17:10, 4F

06/13 17:11, , 5F
struct中的member的大小做一些alignment
06/13 17:11, 5F

06/13 17:13, , 6F
至於case2 前半段應該是uninitialized 其值未定義
06/13 17:13, 6F

06/13 21:26, , 7F
那為什麼後半部是以"bit-field"為單位寫入而不是以Byte呢??
06/13 21:26, 7F

06/14 00:27, , 8F
你不就是定義bit-field嗎? 那自然是以bit為單位讀寫啊.
06/14 00:27, 8F

06/14 00:28, , 9F
是說通常disasm出來看, 還是用一些bit operation去讀/寫
06/14 00:28, 9F

06/14 00:29, , 10F
register, 然後整byte or 整UINT讀/寫回memory去....
06/14 00:29, 10F

06/14 00:47, , 11F
喔喔 測試的結果好像是: unsigned int a:5 =>就以五個bits為
06/14 00:47, 11F

06/14 00:48, , 12F
一組寫回去 就好像把這五個bits當成一個int寫回去 然後像例
06/14 00:48, 12F

06/14 00:49, , 13F
子那樣有多個bit-field的 順序就按照endian順序 不懂的是為
06/14 00:49, 13F

06/14 00:50, , 14F
什麼不是先把所有資料以一個個bit寫好 再以8bits分組寫入記
06/14 00:50, 14F

06/14 00:50, , 15F
憶體 兩種方式最後的結果差蠻多的....
06/14 00:50, 15F

06/14 00:56, , 16F
不太懂你說得是什麼, bit-field就是以其宣告的每一個
06/14 00:56, 16F

06/14 00:57, , 17F
BF的bit數寫起來, 然後照endian順序讀/寫進memory去...
06/14 00:57, 17F

06/14 00:58, , 18F
你想8bits/1byte為group的話, 可以試試
06/14 00:58, 18F

06/14 00:58, , 19F
用unsigned char來定義, ex: unsigned char p1:5 ...etc
06/14 00:58, 19F

06/14 01:08, , 20F
喔喔 跟大大確認一下 bit-field本來就是規定是以宣告的bit數
06/14 01:08, 20F

06/14 01:09, , 21F
為一個group來寫入 不論宣告的數目是1,3,17...之類的 這樣嗎
06/14 01:09, 21F

06/14 01:10, , 22F
那再請問一下是不是alignment也是整個bit-field為單位來移
06/14 01:10, 22F

06/14 01:10, , 23F
動到正確的alignment的位置呢?
06/14 01:10, 23F

06/14 15:17, , 24F

06/14 18:08, , 25F
http://codepad.org/z5jJy7Ay 結果是5411……
06/14 18:08, 25F

06/15 03:32, , 26F
內文加推文看到好多 undefined/unspecific/impl. defined
06/15 03:32, 26F

06/15 03:33, , 27F
像樓上那個是 undefined :P
06/15 03:33, 27F

06/15 04:13, , 28F
XDXD 所以到底是怎麼??? 沒有正確答案嗎??
06/15 04:13, 28F

06/15 04:17, , 29F
所謂的 undefined/unspecific/imp. defined, 指的是
06/15 04:17, 29F

06/15 04:18, , 30F
這問題沒有被規定怎麼實作,你的編譯器爽怎麼做就怎麼做.
06/15 04:18, 30F

06/15 04:19, , 31F
而且可能會帶出讓人想破頭也想不到為什麼的答案。
06/15 04:19, 31F

06/15 04:25, , 32F
那要使用bit-field不就得先找出特性才能使用?? 連基本規則都
06/15 04:25, 32F

06/15 04:25, , 33F
都沒有嗎???
06/15 04:25, 33F

06/15 04:35, , 34F
我建議你別花時間研究 bit-field assignment 上,版上有不
06/15 04:35, 34F

06/15 04:36, , 35F
少人曾認為自己了解bit-field,最後實在是變數太多,把之前
06/15 04:36, 35F

06/15 04:37, , 36F
的認真都打翻。
06/15 04:37, 36F

06/15 04:37, , 37F
^ 認知。
06/15 04:37, 37F

06/15 08:02, , 38F
rifiz: 其實我講「undefined」還不是完整的故事,但我覺得
06/15 08:02, 38F

06/15 08:05, , 39F
與其把標準翻出來慢慢討論... 不如先問你真的需要這麼省嗎
06/15 08:05, 39F

06/15 08:05, , 40F
C 有太多令人崩潰的細節如果你真的有興趣我可以慢慢講 xDD
06/15 08:05, 40F

06/15 09:42, , 41F
我有興趣XDDDDD
06/15 09:42, 41F

06/15 22:56, , 42F
我也有興趣 bit-field我兩個工作都有用到 但資料很少
06/15 22:56, 42F

06/15 22:57, , 43F
用的很心虛 冏
06/15 22:57, 43F

06/16 12:42, , 44F
現在也不太想搞清楚bit-field了 XD, bit-field根本無法節省
06/16 12:42, 44F

06/16 12:43, , 45F
空間除非使用compiler option去configure, 但是這麼做之前又
06/16 12:43, 45F

06/16 12:44, , 46F
得去把某特定compiler翻出來研究一番...挖哩勒....
06/16 12:44, 46F

06/16 12:46, , 47F
之前希望是至少能知道某些通用規則 像是直接assign bit
06/16 12:46, 47F

06/16 12:46, , 48F
pattern, bit-field之間不會有padding(看來也不一定 ORZ)
06/16 12:46, 48F

06/16 12:47, , 49F
總之呢 雖然還是希望能多了解一些 但是EdisonX也不無道理
06/16 12:47, 49F

06/16 12:50, , 50F
Favonia大大 如果可以的話 可分享一下你的資料嗎?? 感謝啦~~
06/16 12:50, 50F

06/17 00:42, , 51F
我是沒用過bit-field擺在union裡面的 不過bit-field絕對
06/17 00:42, 51F

06/17 00:43, , 52F
可以省很多memory 尤其是某class有億以上的實體時
06/17 00:43, 52F

06/17 00:44, , 53F
另外 一般的用法 也不用特地下option
06/17 00:44, 53F

06/17 01:07, , 54F
在小弟遇過的driver裡, bit-field多半與union併用, 常見
06/17 01:07, 54F

06/17 01:07, , 55F
於下command/mmio給HW(register); driver裡依狀況去讀寫
06/17 01:07, 55F

06/17 01:09, , 56F
bit-field對reg的各項參數做設定/取出; 但是mmio讀寫或
06/17 01:09, 56F

06/17 01:10, , 57F
下cmd buffer, 可能就以union起來的DWORD值(視HW而定)整
06/17 01:10, 57F

06/17 01:10, , 58F
段寫入(or讀出)....@_@"
06/17 01:10, 58F

06/17 21:41, , 59F
原來是這種用法 真的很配union+struct 小弟目前作的是
06/17 21:41, 59F

06/17 21:42, , 60F
EDA的 裡面資料量超大 有的case其mem usage可到100GB
06/17 21:42, 60F

06/17 21:42, , 61F
我看到的就是比較單純拿來省mem的用法
06/17 21:42, 61F

06/18 00:00, , 62F
跳個tone,從一開始我很好奇 union A obj = {3,2,4,5}; 這,
06/18 00:00, 62F

06/18 00:01, , 63F
是故意寫成這樣還是筆誤寫錯?
06/18 00:01, 63F

06/18 00:01, , 64F
obj.p1=3, obj.p2=2, obj.p3=4, obj.p4=5 ;
06/18 00:01, 64F

06/18 00:02, , 65F
一些 compiler 支援是 union A obj = {.p1=3,.p2=2,...};
06/18 00:02, 65F

06/18 00:03, , 66F
但任何一本書裡都沒講到原po寫法會怎樣,故好奇問是否筆誤.
06/18 00:03, 66F

06/21 10:24, , 67F
資料就是那些很難讀懂的標準 orz
06/21 10:24, 67F
文章代碼(AID): #1Fs4i8x8 (C_and_CPP)
文章代碼(AID): #1Fs4i8x8 (C_and_CPP)