c++ 结构中填充符的作用是什么?我经常在一些 c++ api 中看到它们。例如:
struct example
{
unsigned short a;
unsigned short b;
char c[3];
char filler1;
unsigned short e;
char filler2;
unsigned int g;
};
该结构旨在通过网络传输
struct example
{
unsigned short a; //2 bytes
unsigned short b;//2 bytes
//4 bytes consumed
char c[3];//3 bytes
char filler1;//1 bytes
//4 bytes consumed
unsigned short e;//2 bytes
char filler2;//1 bytes
//3 bytes consumed ,should be filler[2]
unsigned int g;//4 bytes
};
Because sometimes you don't actually control the format of the data you're using.
The format may be specified by something beyond your control. For example, it may be created in a system with different alignment requirements to yours.
Alternatively, the data may have real data in those filler areas that your code doesn't care about.
通常插入这些填充符以明确确保结构的某些成员自然对齐,即它们在结构内的偏移量是其大小的倍数。
在下面的示例中,假设 char 为 1 个字节,short 为 2,int 为 4。
struct example
{
unsigned short a;
unsigned short b;
char c[3];
char filler1;
unsigned short e; // starts at offset 8
char filler2[2];
unsigned int g; // starts at offset 12
};
如果您不指定任何填充符,编译器通常会添加必要的填充字节以确保结构成员的正确对齐。
顺便说一句,这些字段也可用于将来可能出现的保留字段。
更新:
由于已经提到结构是网络数据包,因此要求填充器获得与从另一主机传递的结构兼容的结构。
但是,在这种情况下插入填充字节可能还不够(尤其是在需要可移植性的情况下)。如果这些结构要按原样通过网络发送(即无需手动打包到单独的缓冲区中进行发送),则必须通知编译器该结构应该被打包。
在 microsoft 编译器中,这可以通过以下方式实现#pragma pack
:
#pragma pack(1)
struct T {
char t;
int i;
short j;
double k;
};
在 gcc 中,您可以使用__attribute__((packed))
struct foo {
char c;
int x;
} __attribute__((packed));
但是,许多人更喜欢手动将结构打包/解包到原始字节数组中,因为可能不 [正确] 支持访问某些系统上未对齐的数据。
根据您正在使用的代码,他们可能会尝试在字边界上对齐结构(在您的情况下为 32 位),这是一种速度优化,但是,像这样的事情已经被体面的优化编译器过时了,但是如果编译器被指示不要优化这段代码,或者编译器非常低端,例如对于嵌入式系统,最好自己处理。它基本上归结为您对编译器的信任程度。
另一个原因是写入二进制文件,其中保留字节已留在文件格式规范中。