什么是C中的“打包”结构?

时间:2011-03-29 13:21:59

标签: 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;

包装是什么意思?

5 个答案:

答案 0 :(得分:59)

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

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

struct S {
    int16_t member1;
    int32_t member2;
};

32位架构中上述结构的内存结构是( =填充):

+---------+---------+
| m1 |~~~~|   m2    |
+---------+---------+

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

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

+---------+---------+
| m1 |   m2    |~~~~
+---------+---------+

答案 1 :(得分:6)

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

例如,请参阅this page

答案 2 :(得分:1)

_attribute__((__packed__))表示(最有可能)“不插入任何填充以使事情更快”,也可能意味着“不要插入任何对齐以保持对齐”。

答案 3 :(得分:1)

尚未明确指出的一件事是,通常进行打包以匹配预定义的字段结构。例如,在网络接口的低层,在联网的机器之间交换一系列字节。接收到数据后,将需要将其映射到高级结构,以便可以轻松操作数据。通常是在没有填充的情况下,这样结构才能直接映射到字节。

网络数据交换还涉及字节字节序问题(即,几乎所有网络数据都使用大字节序格式,而不管源计算机和目标计算机的字节序如何)。

此外,某些计算机不能访问非对齐地址中的宽数据,例如,Cortex-M0内核无法访问非32位对齐地址中的32位数据,因此必须注意在这种情况下需要编写网络代码。

答案 4 :(得分:0)

让我解释一下结构中填充的概念, 然后通过示例打包结构。

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

填充:

struct eg_struct
{
           unsigned char abc;
           unsigned int  xyz;
}

在16位体系结构上按上述声明结构时,将为变量abc分配一些地址。下一个地址未分配给变量xyz,而是添加了一个额外的字节,然后下一个地址将分配给变量xyz

最后,结构如下所示:

struct eg_struct
{
           unsigned char abc;
           unsigned char paddedbytes[1];
           unsigned int  xyz;
}

填充使微控制器可以轻松访问成员变量的地址。 缺点是图片中会多余的字节。

包装:

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

让我举一个需要包装的例子:

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

想象一下,写入EEPROM的功能如下所示:

Write_EEPROM(EEPROM address, Ram address, Byte count);

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