考虑:

struct mystruct_A
{
   char a;
   int b;
   char c;
} x;

struct mystruct_B
{
   int b;
   char a;
} y;

结构尺寸分别为12和8。

这些结构是填充的还是包装的?

什么时候进行填充或包装?


当前回答

这些结构是填充的还是包装的?

它们填充。

最初想到的唯一可能是,如果char和int的大小相同,那么char/int/char结构的最小大小将不允许填充,int/char结构也是如此。

然而,这将要求sizeof(int)和sizeof(char)都为4(以获得12和8的大小)。由于sizeof(char)始终为1的标准保证了整个理论的崩溃。

如果char和int的宽度相同,那么大小将是1和1,而不是4和4。因此,为了得到12的大小,在最终字段之后必须有填充。


什么时候进行填充或包装?

只要编译器实现需要。编译器可以在字段之间和最后一个字段之后(但不能在第一个字段之前)插入填充。

这样做通常是为了性能,因为某些类型在特定边界上对齐时性能更好。甚至有一些架构会在你试图访问未对齐的数据时拒绝运行(即崩溃)(是的,我在看你,ARM)。

您通常可以使用特定于实现的特性(如#pragma pack)来控制打包/填充(这实际上是同一领域的两个极端)。即使您不能在特定的实现中这样做,您也可以在编译时检查代码以确保它满足您的需求(使用标准C特性,而不是特定于实现的东西)。

例如:

// C11 or better ...
#include <assert.h>
struct strA { char a; int  b; char c; } x;
struct strB { int  b; char a;         } y;
static_assert(sizeof(struct strA) == sizeof(char)*2 + sizeof(int), "No padding allowed");
static_assert(sizeof(struct strB) == sizeof(char)   + sizeof(int), "No padding allowed");

如果这些结构中有任何填充,类似这样的东西将拒绝编译。

其他回答

填充和填充只是同一事物的两个方面:

包装或对齐是每个成员四舍五入的大小 填充是为匹配对齐而添加的额外空间

在mystruct_A中,假设默认对齐为4,则每个成员以4字节的倍数进行对齐。因为char的大小是1,所以a和c的填充是4 - 1 = 3个字节,而int b不需要填充,因为它已经是4个字节了。它对mystruct_B的工作方式相同。

只有当你告诉编译器显式地对结构进行打包时,才会进行结构打包。你看到的是填充。您的32位系统正在填充每个字段以字对齐。如果您告诉编译器打包结构,它们将分别为6和5字节。但是不要这样做。它不可移植,使编译器生成的代码更慢(有时甚至有bug)。

填充规则:

结构体的每个成员都应该位于能被其大小整除的地址。 填充在元素之间或结构的末尾插入,以确保满足此规则。这样做是为了硬件更容易和更有效地访问总线。 结构体末尾的填充是根据结构体最大成员的大小决定的。

规则二: 考虑下面的结构,

如果我们要为这个结构体创建一个数组(包含2个结构体), 结束时不需要填充:

因此,struct的大小= 8字节

假设我们要创建另一个结构体,如下所示:

如果我们要创建这个结构体的数组, 最后需要填充的字节数有两种可能。

A.如果我们在末尾添加3个字节,并将其对齐为int而不是Long:

B.如果我们在末尾添加7个字节并将其对齐为Long:

第二个数组的起始地址是8(i)的倍数。e 24)。 struct的大小= 24字节

因此,通过将结构体的下一个数组的起始地址对齐为最大成员(i。E如果我们要创建这个结构体的数组,第二个数组的第一个地址必须从一个地址开始,该地址必须是该结构体最大成员的倍数。这里是24(3 * 8)),我们可以计算出最后所需的填充字节数。

这件事没有但是!想要掌握这门学科必须做到以下几点:

细读埃里克·s·雷蒙德所著的《丢失的结构包装艺术》 看一下Eric的代码示例 最后但并非最不重要的是,不要忘记下面关于填充的规则,即结构体的对齐方式与最大类型的对齐方式一致 要求。

Data structure alignment is the way data is arranged and accessed in computer memory. It consists of two separate but related issues: data alignment and data structure padding. When a modern computer reads from or writes to a memory address, it will do this in word sized chunks (e.g. 4 byte chunks on a 32-bit system) or larger. Data alignment means putting the data at a memory address equal to some multiple of the word size, which increases the system’s performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.

In order to align the data in memory, one or more empty bytes (addresses) are inserted (or left empty) between memory addresses which are allocated for other structure members while memory allocation. This concept is called structure padding. Architecture of a computer processor is such a way that it can read 1 word (4 byte in 32 bit processor) from memory at a time. To make use of this advantage of processor, data are always aligned as 4 bytes package which leads to insert empty addresses between other member’s address. Because of this structure padding concept in C, size of the structure is always not same as what we think.