[問題] Strcut內任一member的offset以及size

看板C_and_CPP (C/C++)作者 (BAY)時間3年前 (2021/06/22 09:34), 3年前編輯推噓10(10039)
留言49則, 9人參與, 3年前最新討論串1/1
開發平台(Platform): (Ex: Win10, Linux, ...) Win10 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) VC,GCC, C language 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) N/A 問題(Question): typedef struct { UINT8 MemberA; UINT16 MemberB; UINT32 MemberC; UINT64 MemberD; ..... UINT8 Reserved[1024]; } Setup; 取得一組數據 並轉型成Setup, 根據這個strcut每一個member一個一個掃過去得到member size 有什麼方法可以做到不知道member名稱下得到任一membert的size? 我知道取得一個member的offset/size可以用offsetof and sizeof offsetof (struct Setup, MemberA); 這方法必須得知道member名稱為MemberA 但目前遇到struct member龐大且不固定 無法指定member 例如上面的struct會變成如下 一個reseved轉成MemberE typedef struct { UINT8 MemberA; UINT16 MemberB; UINT32 MemberC; UINT64 MemberD; ..... UINT8 MemberE; UINT8 Reserved[1023]; } Setup; 煩請高手賜教 餵入的資料(Input): 預期的正確結果(Expected Output): 錯誤結果(Wrong Output): 程式碼(Code):(請善用置底文網頁, 記得排版,禁止使用圖檔) 補充說明(Supplement): -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 110.30.121.152 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1624325692.A.4EA.html

06/22 10:06, 3年前 , 1F
沒 header file ??
06/22 10:06, 1F

06/22 10:54, 3年前 , 2F
有header files 但是code base update struct會變
06/22 10:54, 2F
※ 編輯: shinchun (210.61.233.66 臺灣), 06/22/2021 10:55:40

06/22 11:06, 3年前 , 3F
你只能手動改, C/C++ 沒有其他中繼語言類程式語言中會有的
06/22 11:06, 3F

06/22 11:07, 3年前 , 4F
reflection 類的機制存在 (因為是編譯式語言的關係)
06/22 11:07, 4F

06/22 11:11, 3年前 , 5F
最接近的方式只有讓你的結構能用 get<> 存取
06/22 11:11, 5F

06/22 11:11, 3年前 , 6F
但這仍然需要在結構之外額外定義 get<N> 對這結構的特化
06/22 11:11, 6F

06/22 11:15, 3年前 , 7F
然後以下是我的水晶球: 我猜你大概是想要做些除錯列印
06/22 11:15, 7F

06/22 11:16, 3年前 , 8F
如果只是這樣的話你可以隨著結構額外維護一個列印函數
06/22 11:16, 8F

06/22 11:16, 3年前 , 9F
當結構有改時記得去列印函數裡增減
06/22 11:16, 9F
這個結構也不能隨便動 目的是一樣的struct會有三份數據 NewDefault,OldDefault,user setting compare NewDefault.OldDefault知道那些membe default數值有變動 接著把變動的部分sync to user setting 但是sync to user setting之前又得Compare OldDefault/user setting compare 看看user改過那些setting 這些setting又得保留 ※ 編輯: shinchun (110.30.121.152 臺灣), 06/22/2021 11:54:37

06/22 13:08, 3年前 , 10F
我覺得每個設定多附一個 bool 指示是使用 default / us
06/22 13:08, 10F

06/22 13:08, 3年前 , 11F
er setting 會比較合理
06/22 13:08, 11F

06/22 13:10, 3年前 , 12F
單純比較的話應該是無法分出跟 default 一樣的值到底是
06/22 13:10, 12F

06/22 13:10, 3年前 , 13F
不是 user 指定的
06/22 13:10, 13F

06/22 14:20, 3年前 , 14F
所以其實是成員的遍歷, 只是遍歷處理邏輯類似想抽出來
06/22 14:20, 14F

06/22 14:20, 3年前 , 15F
那這其實就是 visitor pattern, 把遍歷邏輯抽出來之後
06/22 14:20, 15F

06/22 14:21, 3年前 , 16F
寫一個處理函數手動列舉成員遍歷
06/22 14:21, 16F

06/22 14:21, 3年前 , 17F
C++ 有 template 可以把遍歷邏輯寫的簡潔一點
06/22 14:21, 17F

06/22 14:21, 3年前 , 18F
C 只能用 macro 達成類似的效果
06/22 14:21, 18F

06/22 14:22, 3年前 , 19F
但不管哪一個, 列舉成員這件事只能手動
06/22 14:22, 19F

06/22 14:23, 3年前 , 20F
就算要支援 get<> 存取也跑不掉手動指定哪一個抓哪一個
06/22 14:23, 20F
ofsetof sizeof都得指定member name code base也只能用C 沒法用C++ https://github.com/tianocore/edk2 不曉得有什麼macro可以達到掃所有member size? → F04E: 太複雜 跟著一起 update header file 不就好了 06/22 16:10 目前就是有類似的作法 但是maintain effort或是出錯機會比較大

06/22 20:16, 3年前 , 21F
編譯式還是可以有 reflection 啦
06/22 20:16, 21F

06/22 20:16, 3年前 , 22F
像是 idris 的 elab reflection
06/22 20:16, 22F

06/22 20:19, 3年前 , 23F
要做這種事要嘛就是要有很強的類型系統,要嘛就是macro
06/22 20:19, 23F

06/22 20:19, 3年前 , 24F
或編譯器魔法
06/22 20:19, 24F
跪求macro或是編譯器魔法 ※ 編輯: shinchun (110.30.121.152 臺灣), 06/22/2021 21:55:28

06/22 22:04, 3年前 , 25F
編譯器魔法我不知道 但macro你不會想用的 相信我
06/22 22:04, 25F

06/22 22:28, 3年前 , 26F
是說你其實不一定要用 struct 存吧?拿個 string map
06/22 22:28, 26F

06/22 22:28, 3年前 , 27F
之類的用不好嗎?
06/22 22:28, 27F
因為strut一改影響很大

06/23 00:25, 3年前 , 28F
我不是說列舉成員用 macro 喔, 而是說處理函數用 macro 寫
06/23 00:25, 28F

06/23 00:29, 3年前 , 29F
然後手動把所有成員在 visit 函數裡列舉出來這樣
06/23 00:29, 29F

06/23 00:44, 3年前 , 30F
真的硬要的話, 是有一種有點微妙的寫法是
06/23 00:44, 30F

06/23 00:48, 3年前 , 31F
列舉成員也寫成 macro, 然後所有需要成員列表的程式碼改用
06/23 00:48, 31F

06/23 00:48, 3年前 , 32F
這個列舉 macro 來代入 (包含結構定義)
06/23 00:48, 32F

06/23 00:49, 3年前 , 33F
像是 https://ideone.com/R7mgyM 這個樣子
06/23 00:49, 33F

06/23 00:53, 3年前 , 34F
那這個寫法其實初看不好理解, 要新增處理也麻煩
06/23 00:53, 34F

06/23 00:54, 3年前 , 35F
(要多訂一個 macro 再在要的地方引用)
06/23 00:54, 35F

06/23 00:55, 3年前 , 36F
(↑事實上這個新 macro 就是我這段推文第一行說的處理函數)
06/23 00:55, 36F

06/23 00:56, 3年前 , 37F
那就看你的需求值不值得把結構和它的處理寫成這種麻煩樣了
06/23 00:56, 37F
感謝各位高手 看來我得試試看UEFI架構內的別的方法試試看 ※ 編輯: shinchun (110.30.121.152 臺灣), 06/23/2021 16:07:29

06/23 18:13, 3年前 , 38F
這不是交給版本管理處理就好...
06/23 18:13, 38F

06/24 10:18, 3年前 , 39F
這種需求應該是firmware會需要的...XDD
06/24 10:18, 39F

06/24 10:18, 3年前 , 40F
我也有類似的需求,還真不知道怎麼做
06/24 10:18, 40F

06/24 10:48, 3年前 , 41F
嘛, 上面這招我是從 LLVM 學來的...
06/24 10:48, 41F

06/24 10:48, 3年前 , 42F
裡面有很多需要手動列舉某類的所有東西的定義和處理
06/24 10:48, 42F

06/24 10:49, 3年前 , 43F
這時他們會把列舉出來的這些東西獨立寫成一個 .def 檔案
06/24 10:49, 43F

06/24 10:50, 3年前 , 44F
當需要這份列舉時就定義處理的 macro 再引入該 .def 檔即可
06/24 10:50, 44F

06/24 10:50, 3年前 , 45F
我上面的寫法只是把那個 .def 檔案再寫成一個 macro 而已
06/24 10:50, 45F

06/24 10:52, 3年前 , 46F
那這裡原 PO 的要求裡正好列舉的東西是某結構的所有成員
06/24 10:52, 46F

06/24 11:58, 3年前 , 47F
上面不就是把結構的定義獨立到def檔... 追根究底不就是版本
06/24 11:58, 47F

06/24 15:48, 3年前 , 48F
如果不要求用struct, 可以用protobuf format
06/24 15:48, 48F

06/24 19:24, 3年前 , 49F
第一次看到用X macro來宣告結構成員 學習了
06/24 19:24, 49F
文章代碼(AID): #1WqJuyJg (C_and_CPP)
文章代碼(AID): #1WqJuyJg (C_and_CPP)