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

s1ag04yj  于 2022-12-03  发布在  其他
关注(0)|答案(6)|浏览(429)

我正在浏览为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;

打包是什么意思?

jc3wubiy

jc3wubiy1#

定义结构时,允许编译器添加填充(没有实际数据的空格),以便成员落在CPU更容易访问的地址边界内。
例如,在32比特CPU上,32比特成员应该从4字节倍数的位址开始,才能有效率地存取(读取和写入)。下列结构定义会在两个成员之间加入16比特填补,让第二个成员福尔斯在适当的位址界限内:

struct S {
    int16_t member1;
    int32_t member2;
};

上述结构在32位体系结构中的存储器中的结构是(~=填充):

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

当一个结构被打包时,这些填充并不被插入。编译器必须生成更多的代码(运行速度较慢)来提取未对齐的数据成员,并写入它们。
相同的结构在打包后将在内存中显示为如下形式:

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

watbbzwu2#

它指示编译器不要在struct的成员之间添加任何填充。
例如,请参阅this page

brtdzjyr

brtdzjyr3#

让我通过一个例子来解释结构中填充的概念,然后解释打包结构。
然后让我们看看为什么需要 Package 。

填充:

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;
}

填充使得微控制器可以很容易地访问成员变量的地址。缺点是额外的不必要的字节进入画面。

** Package :**

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

让我给予一个需要 Package 的例子:

考虑与EEPROM接口的微控制器,其中存储了一些结构。
假设一个写入EEPROM的函数如下所示:

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

现在,如果不进行打包,额外填充的字节将占用EEPROM中的空间,这是无用的。

myss37ts

myss37ts4#

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

tzcvj98z

tzcvj98z5#

有一点没有明确指出,即打包通常是为了匹配预定义的字段结构。例如,在网络接口的低层,联网的机器之间交换一系列字节。接收到数据后,需要将其Map到高层结构,以便可以轻松地处理数据。这是通常不需要填充的情况。以便该结构直接Map到字节。
网络数据交换还涉及字节存储顺序问题(即,几乎所有网络数据都使用大字节存储顺序格式,而不管源计算机和目标计算机的字节存储顺序如何)。
此外,有些机器无法访问非对齐地址中的宽数据,例如,Cortex-M0内核无法访问非32位对齐地址中的32位数据,因此在这种情况下编写网络代码时必须小心。

zz2j4svz

zz2j4svz6#

当在结构声明期间使用packed时,编译器不会向同一结构的成员添加任何填充。下面是示例代码和输出,这是不言自明的。

$ cat structure_packed.c
#include <stdio.h>

typedef struct __attribute__((__packed__))
{
        char a;
        int ai;
        char ac;
}A;

struct B
{
        char b;
        int bi;
        char bc;
};

int main()
{
         A a;
        struct B b;
        int c;
        printf("size of struct A: %lu, addr a: %p, addr ai: %p, addr ac: %p\n", sizeof(a), &(a.a), &(a.ai), &a.ac);
        printf("size of struct B: %lu, addr b: %p, addr bi: %p, addr bc: %p\n", sizeof(b), &(b.b), &(b.bi), &b.bc);
        printf("addr of c: %p\n", &c);
        return 0;
}

编译

$ 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

相关问题