39

我正在研究一些为 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;

打包是什么意思?

4

5 回答 5

85

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

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

struct S {
    int16_t member1;
    int32_t member2;
};

上述结构在 32 位架构中的内存结构为(~ =padding):

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

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

相同的结构在打包后会出现在内存中,如下所示:

+---------+---------+
| m1 |   m2    |~~~~
+---------+---------+
于 2011-03-29T13:24:44.637 回答
8

它指示编译器不要在struct.

例如,请参阅此页面

于 2011-03-29T13:24:52.400 回答
4

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

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

填充:

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

当结构在 16 位架构上如上声明时,变量abc将被分配一些地址。下一个地址没有分配给 variable xyz,而是添加了一个额外的字节,然后下一个地址将分配给 variable 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中的空间,这是没有用的。

于 2019-04-28T17:49:50.520 回答
1

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

于 2011-03-29T13:45:27.477 回答
1

没有明确指出的一件事是打包通常是为了匹配预定义的字段结构。例如,在网络接口的底层,网络机器之间交换一系列字节。接收到数据后,需要将其映射到高级结构,以便轻松操作数据。这是通常不需要填充的时候,因此结构直接映射到字节。

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

此外,有些机器无法访问非对齐地址中的宽数据,例如,Cortex-M0 内核无法访问非 32 位对齐地址中的 32 位数据,因此在这种情况下编写网络代码时必须小心。

于 2019-04-30T19:42:12.937 回答