C语言 什么是 C 中的“打包”结构?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5473189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is a "packed" structure in C?
提问by PICyourBrain
I am going though some C code written for the Microchip C30 compiler and I often see structs defined as follows:
我正在阅读一些为 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;
What does packed mean?
打包是什么意思?
回答by Juliano
When structures are defined, the compiler is allowed to add paddings (spaces without actual data) so that members fall in address boundaries that are easier to access for the CPU.
定义结构时,允许编译器添加填充(没有实际数据的空格),以便成员位于 CPU 更容易访问的地址边界内。
For example, on a 32-bit CPU, 32-bit members should start at addresses that are multiple of 4 bytes in order to be efficiently accessed (read and written). The following structure definition adds a 16-bit padding between both members, so that the second member falls in a proper address boundary:
例如,在 32 位 CPU 上,32 位成员应该从 4 字节的倍数的地址开始,以便有效地访问(读取和写入)。以下结构定义在两个成员之间添加了 16 位填充,以便第二个成员落入正确的地址边界:
struct S {
int16_t member1;
int32_t member2;
};
The structure in memory of the above structure in a 32-bit architecture is (~= padding):
32位架构中上述结构在内存中的结构为(~=padding):
+---------+---------+
| m1 |~~~~| m2 |
+---------+---------+
When a structure is packed, these paddings are not inserted. The compiler has to generate more code (which runs slower) to extract the non-aligned data members, and also to write to them.
当一个结构被打包时,这些填充不会被插入。编译器必须生成更多代码(运行速度较慢)来提取未对齐的数据成员,并写入它们。
The same structure, when packed, will appear in memory as something like:
相同的结构,打包后,将在内存中显示为:
+---------+---------+
| m1 | m2 |~~~~
+---------+---------+
回答by NPE
回答by Vatine
_attribute__((__packed__))means (most probably) "do not insert any padding to make things faster" and may also mean "do not insert any alignments to preserve alignment".
_attribute__((__packed__))意味着(很可能)“不插入任何填充以使事情更快”,也可能意味着“不插入任何对齐以保持对齐”。
回答by Babajan
Let me explain the concept of padding in structures and then packed structures by taking an example.
让我通过一个例子来解释在结构中填充然后压缩结构的概念。
And then let us see why packing is required.
然后让我们看看为什么需要包装。
Padding:
填充:
struct eg_struct
{
unsigned char abc;
unsigned int xyz;
}
When the structure is declared as above on a 16 bit architecture, the variable abcwould be assigned some address. The next address is not assigned to variable xyz, instead one extra byte is added, and then the next address would be assigned to the variable xyz.
当在 16 位架构上如上声明结构体时,变量abc将被分配一些地址。下一个地址不分配给变量xyz,而是添加一个额外的字节,然后下一个地址将分配给变量xyz。
In the end, the structure looks something like below:
最后,结构如下所示:
struct eg_struct
{
unsigned char abc;
unsigned char paddedbytes[1];
unsigned int xyz;
}
Padding makes addresses of member variables easily accessible to the microcontroller. The disadvantage is extra unnecessary bytes that come into the picture.
填充使微控制器可以轻松访问成员变量的地址。缺点是进入图片的额外不必要的字节。
Packing:
包装:
If same structure is declared using the attribute “packed”, the extra byte will not be added after the variable abc.
如果使用属性“ packed”声明相同的结构,则不会在变量后添加额外的字节abc。
Let me give one example where packing is needed:
让我举一个需要打包的例子:
Consider a microcontroller interfaced with an EEPROM where some structure is being stored.
考虑一个与 EEPROM 接口的微控制器,其中存储了一些结构。
Imagine a function writing to the EEPROM would look as below:
想象一个写入 EEPROM 的函数如下所示:
Write_EEPROM(EEPROM address, Ram address, Byte count);
Now if packing is not done, the extra padded bytes would occupy space in the EEPROM, which is of no use.
现在如果不打包,多余的填充字节会占用 EEPROM 中的空间,这是没有用的。
回答by Richard at ImageCraft
One thing that has not been explicitly called out is that packing usually is done to match predefined field structures. For example, at the low level layer of a network interface, a series of bytes is exchanged between networked machines. After the data is received, it will need to be mapped to a high level structure so that the data can be manipulated easily. This is when no-padding is usually necessary, so that the structure directly maps to the bytes.
没有明确指出的一件事是打包通常是为了匹配预定义的字段结构。例如,在网络接口的低层,联网机器之间交换一系列字节。接收到数据后,需要将其映射到高层结构,以便轻松操作数据。这是通常需要无填充的时候,以便结构直接映射到字节。
Network data interchange also involves byte endianness issue (i.e. almost all network data uses big endian format regardless the endianness of the source and destination machines).
网络数据交换还涉及字节字节序问题(即几乎所有网络数据都使用大字节序格式,而不管源和目标机器的字节序如何)。
Furthermore, some machines cannotaccess wide data in non-aligned address, for example, Cortex-M0 cores cannot access 32-bit data in non-32-bit aligned address, so care must be taken on writing networking code in such cases.
此外,有些机器无法访问非对齐地址的宽数据,例如 Cortex-M0 内核无法访问非 32 位对齐地址的 32 位数据,因此在这种情况下编写网络代码时必须小心。

