我在C程序中有以下结构。
typedef struct
{
unsigned char msg_id : 8;
unsigned char msg_num : 8;
} Message_Header_Type;
typedef struct
{
Message_Header_Type header;
int msg[32];
} Raw_Message_Type;
我所看到的是,Raw_Message_Type中的标头占用了4个字节,但我只想要它只占2个。我将如何进行此操作?
答案 0 :(得分:3)
您正在寻找的是 struct packing ,它取决于平台和编译器,详细信息未在C标准中指定。
使用GCC,在32位平台上,您可以执行以下操作以获取大小为2的结构:
typedef struct __attribute__((__packed__))
{
unsigned char msg_id;
unsigned char msg_num;
} Message_Header_Type;
来自GCC文件:
packed
此属性附加到枚举,结构或联合类型定义,指定使用最小所需内存来表示类型。
答案 1 :(得分:2)
Message_Header_type
内的{p> Raw_Message_Type
仍然按照您的预期占用2个字节,但编译器为了对齐原因填充结构,因此Raw_Message_Type
长度为132个字节而不是你期望的130个字节。这可能是因为32位对齐访问在处理器上更有效。
如果您正在使用gcc,则可以告诉编译器使用#pragma pack
对齐2字节边界而不是它正在使用的4字节边界。
typedef struct
{
unsigned char msg_id : 8;
unsigned char msg_num : 8;
} Message_Header_Type;
#pragma pack(push, 2) // save current alignment and set to 2-byte boundaries
typedef struct
{
Message_Header_Type header;
int msg[32];
} Raw_Message_Type;
#pragma pack(pop) // restore the previous alignment
在文件中使用固定大小的结构时,通常需要这样的特殊包装,但请注意,使用与处理器不同的包装可能会导致(轻)性能损失。在这种特定情况下,您的32 msg [] int
现在与您平台的首选路线相距2个字节。
答案 2 :(得分:1)
C实现可以自由地在成员之间,最后或两者之间插入填充struct
布局。他们通常这样做是为了对齐目的。编译器通常也提供影响或覆盖填充的机制,但细节必须是特定于实现的。
例如,使用GCC,您可以将packed
属性应用于structs
:
typedef struct __attribute__((__packed__))
{
unsigned char msg_id : 8;
unsigned char msg_num : 8;
} Message_Header_Type;
typedef struct __attribute__((__packed__))
{
Message_Header_Type header;
int msg[32];
} Raw_Message_Type;
其他一些实施借鉴了GCC的方法;有些人使用pragma
来达到同样的目的;还有一些提供其他机制。您需要检查编译器的文档。
答案 3 :(得分:0)
不保证结构对象的成员位字段中使用的位总和的大小。这是因为填充。
在您的情况下,Raw_Message_Type
还有其他成员int msg[32];
。将两个以上的字节用于目的对齐似乎是合乎逻辑的,这样msg [0]就可以与4字节边界对齐。
很有可能
Message_Header_Type obj;
printf("Size : %zu\n",sizeof(obj));
会给你2作为结果。