什么是C中的"打包"结构?

PIC*_*ain 30 c microcontroller packed

我将为Microchip C30编译器编写一些C代码,我经常看到结构定义如下:

typedef struct __attribute__((__packed__)) 
{
    IP_ADDR     MyIPAddr;               // IP address
    IP_ADDR     MyMask;                 // Subnet mask
    IP_ADDR     MyGateway;              // Default Gateway
        // etc...
} APP_CONFIG;
Run Code Online (Sandbox Code Playgroud)

包装是什么意思?

Jul*_*ano 63

定义结构时,允许编译器添加填充(没有实际数据的空格),以便成员落入更容易访问CPU的地址边界.

例如,在32位CPU上,32位成员应从4个字节的多个地址开始,以便有效地访问(读取和写入).以下结构定义在两个成员之间添加了一个16位填充,以便第二个成员落在适当的地址边界:

struct S {
    int16_t member1;
    int32_t member2;
};
Run Code Online (Sandbox Code Playgroud)

在32位架构中上述结构的存储器结构是( = padding):

+---------+---------+
| m1 |~~~~|   m2    |
+---------+---------+
Run Code Online (Sandbox Code Playgroud)

当打包结构时,不插入这些填充.编译器必须生成更多代码(运行速度较慢)以提取未对齐的数据成员,并写入它们.

打包时,相同的结构将在内存中显示为:

+---------+---------+
| m1 |   m2    |~~~~
+---------+---------+
Run Code Online (Sandbox Code Playgroud)

  • 切题的问题,但如果它会让事情变得更慢,为什么要创建一个打包结构呢?是为了减少内存占用吗? (2认同)
  • 一个用例:它们经常用于定义和实现网络协议、二进制格式……您通常不想向将要存储或通过网络发送的结构添加填充。 (2认同)
  • @Maxitj,48位是6个字节,而不是12个。 (2认同)

Bab*_*jan 7

让我通过一个例子来解释结构中填充和打包结构的概念。

然后让我们看看为什么需要包装。

填充:

struct eg_struct
{
           unsigned char abc;
           unsigned int  xyz;
}
Run Code Online (Sandbox Code Playgroud)

当在 16 位架构上按上述方式声明结构时,变量abc将被分配一些地址。下一个地址不会分配给变量xyz,而是添加一个额外的字节,然后下一个地址将分配给变量xyz

最后,结构如下所示:

struct eg_struct
{
           unsigned char abc;
           unsigned char paddedbytes[1];
           unsigned int  xyz;
}
Run Code Online (Sandbox Code Playgroud)

填充使微控制器可以轻松访问成员变量的地址。缺点是图像中出现了额外的不必要的字节。

包装:

如果使用属性“ packed”声明相同的结构,则变量后面不会添加额外的字节abc

我举一个需要打包的例子:

考虑一个与 EEPROM 连接的微控制器,其中存储了一些结构。

想象一下写入 EEPROM 的函数如下所示:

Write_EEPROM(EEPROM address, Ram address, Byte count);
Run Code Online (Sandbox Code Playgroud)

现在如果不进行打包,多余的填充字节将占用 EEPROM 中的空间,这是没有用的。


NPE*_*NPE 6

它指示编译器不在成员之间添加任何填充struct.

例如,请参阅此页面.