typedef struct BaseMessage
{
int u32DeviceID : 32;
int u32CoreID : 32;
unsigned int u16Class : 16;
unsigned int u8OpCode : 8;
unsigned int u16CRC : 16;
} BaseMessage;
typedef struct MessageWithParameters
{
BaseMessage base;
int u8Param1 : 8;
int u8Param2 : 8;
} MessageWithParameters;
typedef struct FullMessage
{
int u32DeviceID : 32;
int u32CoreID : 32;
unsigned int u16Class : 16;
unsigned int u8OpCode : 8;
unsigned int u16CRC : 16;
int u8Param1 : 8;
int u8Param2 : 8;
} FullMessage;
int main()
{
printf("%d", sizeof(MessageWithParameters));
printf("%d", sizeof(FullMessage));
}
在MessageWithParameters
BaseMessage
中,MessageWithParameters
自身的尺寸不是很大吗?
即使它在堆栈上?
我猜测编译器会将FullMessage
变为看起来像{{1}}的东西
我是对的吗?
答案 0 :(得分:2)
我猜你有一些填充问题。基数有24位“剩余”,参数struct中添加的16位可以容纳在其中。你为什么使用位域?他们被普遍谴责为一个坏主意。
答案 1 :(得分:1)
我猜测编译器会将
MessageWithParameters
变为看起来像FullMessage
的东西 我是对的吗?
没有人能这么说。编译器可以自由决定。该标准保证成员订单,并且在第一个成员(包括派生成员)之前没有填充。
答案 2 :(得分:1)
正如其他人所说,你会遇到结构的填充物。 C语言本身没有任何东西可以有效地防止这种情况。您的编译器可能对 pack 事物有一些扩展,例如gcc将其实现为attribute
。但是为了让事情变得非常紧密,那么你需要按照升序或降序对字段进行重新排序,以使对齐间隙尽可能小。
此外,对这种结构使用位域通常是个坏主意。如果你有它们使用C99固定大小的整数类型,如下所示:
typedef struct BaseMessage
{
int32_t u32DeviceID;
int32_t u32CoreID;
uint16_t u16Class;
uint16_t u16CRC;
uint8_t u8OpCode;
} BaseMessage;
在这种情况下,如果您的编译器以16位(这些天很少见)对齐,您只需浪费BaseMessage
的其他8位。