在这种情况下尾随填充字节的重要性是什么?

What is the importance of trailing padding bytes in that case?

我有以下类型的结构:

typedef struct
{
   unsigned char      A;
   unsigned long int  B;
   unsigned short int C;
}

根据每个基本数据类型的对齐要求和整个结构体的对齐要求,在内存中的分配是这样的:

我的问题是那些尾部填充字节的重要性是什么,只要每个结构成员自然地与其大小对齐并且可以在一个周期内被我们的处理器访问(假设处理器的总线大小为 32-位)没有对齐错误。

此外,如果我们声明一个“2”的数组,不考虑尾部字节,内存分配如下:

两个结构中的每个成员都自然地与其大小对齐,并且可以在一个周期内访问而不会出现对齐错误。 那么,在这种情况下尾随字节的重要性是什么?!

Bryan Olivier 和 Hans Passant 的评论都是正确的。

基本上,你已经回答了你自己的问题:在第二张图中,第一个和第二个数组项的成员的对齐方式都是正确的。如果编译器可以像这样布局结构,那么尾随填充字节就不重要了。但是不能。

在 C 语言中,结构的每个实例的结构布局和大小必须相同。在您的第二个示例中,sizeof(array[0]) 为 10,sizeof(array[1]) 为 8。B2 的地址仅比 A2 大两倍,但 &B1 比 &A1 大四倍。

它不仅仅是对齐 - 它确保布局和大小不变,同时仍然确保对齐。即使这样,如果第一个字节对齐,它也不需要尾随填充字节,但正如您所注意到的,如果您添加数组,那么您就需要它们。

Alignment+Layout/Size+Arrays => trailing pad is required.

正如 Andres 所说,编译器无法为结构数组中的每个成员生成特殊布局。

例如,假设程序员定义了一个具有以下类型的结构

typedef struct
{
   unsigned char      A;
   unsigned long int  B;
   unsigned short int C;
} myStructureType;

然后程序员创建了这个类型的实例:

myStructureType myStructure;

编译器将如下分配内存给myStructure

如果程序员决定创建一个 myStructureType 的数组,编译器将在内存中按照数组元素的数量重复之前的模式,如下所示:

如果编译器忽略尾部填充字节,内存将变得不对齐,如下所示

32 位现代处理器将需要两个内存周期和一些屏蔽操作来获取 B1(结构数组索引“1”中的元素 B)。但是,旧处理器会引发对齐错误。

这就是尾部填充在这种情况下很重要的原因