2

c++ 结构中填充符的作用是什么?我经常在一些 c++ api 中看到它们。例如:

struct example
{
    unsigned short a;
    unsigned short b;
    char c[3];
    char filler1;
    unsigned short e;
    char filler2;
    unsigned int g;
};

该结构旨在通过网络传输

4

4 回答 4

6
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
};
于 2012-08-09T06:34:23.793 回答
4

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.

于 2012-08-09T06:32:30.193 回答
3

通常插入这些填充符以明确确保结构的某些成员自然对齐,即它们在结构内的偏移量是其大小的倍数。

在下面的示例中,假设 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));

但是,许多人更喜欢手动将结构打包/解包到原始字节数组中,因为可能不 [正确] 支持访问某些系统上未对齐的数据。

于 2012-08-09T06:40:08.410 回答
1

根据您正在使用的代码,他们可能会尝试在字边界上对齐结构(在您的情况下为 32 位),这是一种速度优化,但是,像这样的事情已经被体面的优化编译器过时了,但是如果编译器被指示不要优化这段代码,或者编译器非常低端,例如对于嵌入式系统,最好自己处理。它基本上归结为您对编译器的信任程度。

另一个原因是写入二进制文件,其中保留字节已留在文件格式规范中。

于 2012-08-09T06:38:46.150 回答