Tra*_*ggs 4 c gcc struct nested
假设我有用于模拟各种数据包格式的结构:
#define MaxPacket 20
typedef struct {
u8 packetLength;
union {
u8 bytes[MaxPacket];
struct {
u16 field1;
u16 field2;
u16 field3;
} format1;
struct {
double value1;
double value2;
} format2;
};
} Packet;
Run Code Online (Sandbox Code Playgroud)
我可以预期那sizeof(Packet)将是21。但是有什么办法可以做这样的事情:
sizeof(Packet.format2)
Run Code Online (Sandbox Code Playgroud)
? 我试过了,但编译器不满意。显然,我可以将其format1作为单独的 typedef 取出,然后我可以sizeof(format1). 但我很好奇我是否必须经历这一切。我喜欢格式的层次结构。这是在 8 位处理器上使用 gcc。
如果有办法使用嵌套类型,我同样感兴趣。如果我必须做很多
aPacketPointer->format2.value1; // not so onerous, but if the nesting gets deeper...
Run Code Online (Sandbox Code Playgroud)
那么有时这样做会很好:
Packet.format2 *formatPtr = &aPacketPointer->format2;
formatPtr->value2; // etc
Run Code Online (Sandbox Code Playgroud)
同样,重构为一堆前面的 typedef 可以解决这个问题,但是我失去了嵌套点引用的良好命名空间效果。
对于即使在 C90 中也能工作的东西,您可以使用以您的工具链的offsetof()宏为模型的宏:
#define sizeof_field(s,m) (sizeof((((s*)0)->m)))
Run Code Online (Sandbox Code Playgroud)
如果您的工具链的offsetof()宏不是基于转换0为指向结构类型的指针,则相应地调整它。
当我像这样使用它时:
std::cout << sizeof_field(Packet,format1) << std::endl;
std::cout << sizeof_field(Packet,format2) << std::endl;
Run Code Online (Sandbox Code Playgroud)
我得到输出:
6
16
Run Code Online (Sandbox Code Playgroud)
对于您的第二个问题,如果您愿意依赖 GCC 的typeof扩展,您可以创建一个类似的宏来声明指向嵌套匿名结构的指针:
#define typeof_field(s,m) typeof(((s*)0)->m)
...
typeof_field(Packet,format2)* f2 = &foo.format2;
Run Code Online (Sandbox Code Playgroud)
老实说,我发现这种构造非常丑陋,但它可能仍然比您可用的其他选项更好。
GCC 记录了“当且仅当它是可变修改类型的表达式或此类类型的名称时,才会评估 typeof 的操作数的副作用”,因此当变量为变量时,明显的空指针引用不应导致未定义的行为不涉及长度数组。