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

作者: shinchun (BAY)   2021-06-22 09:34:50
開發平台(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):
作者: F04E (Fujitsu)   2021-06-22 10:06:00
沒 header file ??
作者: shinchun (BAY)   2021-06-22 10:54:00
有header files 但是code base update struct會變
作者: LPH66 (-6.2598534e+18f)   2021-06-22 11:06:00
你只能手動改, C/C++ 沒有其他中繼語言類程式語言中會有的reflection 類的機制存在 (因為是編譯式語言的關係)最接近的方式只有讓你的結構能用 get<> 存取但這仍然需要在結構之外額外定義 get<N> 對這結構的特化然後以下是我的水晶球: 我猜你大概是想要做些除錯列印如果只是這樣的話你可以隨著結構額外維護一個列印函數當結構有改時記得去列印函數裡增減
作者: Lipraxde (Lipraxde)   2021-06-22 13:08:00
我覺得每個設定多附一個 bool 指示是使用 default / user setting 會比較合理單純比較的話應該是無法分出跟 default 一樣的值到底是不是 user 指定的
作者: LPH66 (-6.2598534e+18f)   2021-06-22 14:20:00
所以其實是成員的遍歷, 只是遍歷處理邏輯類似想抽出來那這其實就是 visitor pattern, 把遍歷邏輯抽出來之後寫一個處理函數手動列舉成員遍歷C++ 有 template 可以把遍歷邏輯寫的簡潔一點C 只能用 macro 達成類似的效果但不管哪一個, 列舉成員這件事只能手動就算要支援 get<> 存取也跑不掉手動指定哪一個抓哪一個
作者: CoNsTaR ((const *))   2021-06-22 20:16:00
編譯式還是可以有 reflection 啦像是 idris 的 elab reflection要做這種事要嘛就是要有很強的類型系統,要嘛就是macro或編譯器魔法
作者: sarafciel (Cattuz)   2021-06-22 22:04:00
編譯器魔法我不知道 但macro你不會想用的 相信我
作者: Lipraxde (Lipraxde)   2021-06-22 22:28:00
是說你其實不一定要用 struct 存吧?拿個 string map之類的用不好嗎?
作者: LPH66 (-6.2598534e+18f)   2021-06-23 00:25:00
我不是說列舉成員用 macro 喔, 而是說處理函數用 macro 寫然後手動把所有成員在 visit 函數裡列舉出來這樣真的硬要的話, 是有一種有點微妙的寫法是列舉成員也寫成 macro, 然後所有需要成員列表的程式碼改用這個列舉 macro 來代入 (包含結構定義)像是 https://ideone.com/R7mgyM 這個樣子那這個寫法其實初看不好理解, 要新增處理也麻煩(要多訂一個 macro 再在要的地方引用)(↑事實上這個新 macro 就是我這段推文第一行說的處理函數)那就看你的需求值不值得把結構和它的處理寫成這種麻煩樣了
作者: F04E (Fujitsu)   2021-06-23 18:13:00
這不是交給版本管理處理就好...
作者: james732 (好人超)   2021-06-24 10:18:00
這種需求應該是firmware會需要的...XDD我也有類似的需求,還真不知道怎麼做
作者: LPH66 (-6.2598534e+18f)   2021-06-24 10:48:00
嘛, 上面這招我是從 LLVM 學來的...裡面有很多需要手動列舉某類的所有東西的定義和處理這時他們會把列舉出來的這些東西獨立寫成一個 .def 檔案當需要這份列舉時就定義處理的 macro 再引入該 .def 檔即可我上面的寫法只是把那個 .def 檔案再寫成一個 macro 而已那這裡原 PO 的要求裡正好列舉的東西是某結構的所有成員
作者: F04E (Fujitsu)   2021-06-24 11:58:00
上面不就是把結構的定義獨立到def檔... 追根究底不就是版本
作者: kokal (細菌)   2021-06-24 15:48:00
如果不要求用struct, 可以用protobuf format
作者: chuegou (chuegou)   2021-06-24 19:24:00
第一次看到用X macro來宣告結構成員 學習了
作者: LPH66 (-6.2598534e+18f)   2021-06-27 04:29:00
版本嗎...我覺得這有點搞錯原 PO 在問的東西原 PO 想問的是結構成員和列舉其處理的程式碼間的同步問題(然後以為用 offsetof 可以反過來列舉才會用這標題)把它丟版本只是被動地紀錄誰改了什麼, 實際處理的程式碼依然得要手動改, 而這手動改的問題才是原 PO 要問的
作者: adxis (Acquire higher)   2021-06-29 13:12:00

Links booklink

Contact Us: admin [ a t ] ucptt.com