[问题] 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