我正在浏览为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;
打包是什么意思?
6条答案
按热度按时间jc3wubiy1#
定义结构时,允许编译器添加填充(没有实际数据的空格),以便成员落在CPU更容易访问的地址边界内。
例如,在32比特CPU上,32比特成员应该从4字节倍数的位址开始,才能有效率地存取(读取和写入)。下列结构定义会在两个成员之间加入16比特填补,让第二个成员福尔斯在适当的位址界限内:
上述结构在32位体系结构中的存储器中的结构是(~=填充):
当一个结构被打包时,这些填充并不被插入。编译器必须生成更多的代码(运行速度较慢)来提取未对齐的数据成员,并写入它们。
相同的结构在打包后将在内存中显示为如下形式:
watbbzwu2#
它指示编译器不要在
struct
的成员之间添加任何填充。例如,请参阅this page。
brtdzjyr3#
让我通过一个例子来解释结构中填充的概念,然后解释打包结构。
然后让我们看看为什么需要 Package 。
填充:
当在16位体系结构上如上声明该结构时,变量
abc
将被分配某个地址。下一个地址不被分配给变量xyz
,而是添加一个额外的字节,然后下一个地址将被分配给变量xyz
。最后,结构看起来如下所示:
填充使得微控制器可以很容易地访问成员变量的地址。缺点是额外的不必要的字节进入画面。
** Package :**
如果使用属性“
packed
“声明相同的结构,则不会在变量abc
之后添加额外的字节。让我给予一个需要 Package 的例子:
考虑与EEPROM接口的微控制器,其中存储了一些结构。
假设一个写入EEPROM的函数如下所示:
现在,如果不进行打包,额外填充的字节将占用EEPROM中的空间,这是无用的。
myss37ts4#
_attribute__((__packed__))
意味着(最有可能)“不插入任何填充以使事情更快”,也可能意味着“不插入任何对齐以保留对齐”。tzcvj98z5#
有一点没有明确指出,即打包通常是为了匹配预定义的字段结构。例如,在网络接口的低层,联网的机器之间交换一系列字节。接收到数据后,需要将其Map到高层结构,以便可以轻松地处理数据。这是通常不需要填充的情况。以便该结构直接Map到字节。
网络数据交换还涉及字节存储顺序问题(即,几乎所有网络数据都使用大字节存储顺序格式,而不管源计算机和目标计算机的字节存储顺序如何)。
此外,有些机器无法访问非对齐地址中的宽数据,例如,Cortex-M0内核无法访问非32位对齐地址中的32位数据,因此在这种情况下编写网络代码时必须小心。
zz2j4svz6#
当在结构声明期间使用packed时,编译器不会向同一结构的成员添加任何填充。下面是示例代码和输出,这是不言自明的。
编译
$ gcc结构_压缩. c-o结构_压缩
运行|输出**
$ ./结构封装
结构A大小:6,地址a:0x 7 ffc 6 f177 ed 6,地址ai:0x 7 ffc 6 f177 ed 7,地址:0x 7有效位6 f177 edb
结构B大小:12、地址B:0x 7 ffc 6 f177 edc,地址bi:0x 7 ffc 6 f177 ee 0,地址BC:0x 7有效位数
地址:0x 7 ffc 6 f177 ed 0