【发布时间】:2023-03-19 02:54:01
【问题描述】:
假设我有用于建模各种数据包格式的结构:
#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;
我可以预期sizeof(Packet) 将是21。但是有没有办法做类似的事情:
sizeof(Packet.format2)
?我试过了,但编译器不高兴。显然,我可以将format1 作为单独的typedef 拉出,然后我可以sizeof(format1)。但我很好奇我是否必须经历所有这些。我喜欢格式的层次结构。这是在 8 位处理器上使用 gcc。
如果有使用嵌套类型的方法,我同样感兴趣。如果我必须做很多事情
aPacketPointer->format2.value1; // not so onerous, but if the nesting gets deeper...
那么有时这样做会很好:
Packet.format2 *formatPtr = &aPacketPointer->format2;
formatPtr->value2; // etc
再一次,重构成一堆前面的 typedef 可以解决这个问题,但是我失去了嵌套点引用的良好命名空间效果。
【问题讨论】:
-
您可能认为
sizeof(Packet)将是 21,但在我尝试过的至少两个编译器配置上,它的结果为 32。也许这对您的使用不会有问题,因为至少它比您预期的要大(另一方面,也许这是一个问题)。其他可能让您感到惊讶的是,包含bytes、format和format2的union的偏移量为8 - 编译器在packetLength字段和联合之间放置了填充。在 C/C++ 结构中建模在线数据对象时需要非常小心。 -
请记住,@MichaelBurr 可能正在使用 32b 架构进行测试,默认情况下所有内容都会被填充。 8b 处理器编译器不进行填充。反正我也没见过。
-
是的。为了通过有线协议将字节转换为结构,从一个基本假设开始,即您可以强制并信任您的结构布局。不同的编译器通常有不同的机制来执行此操作。