我有以下类型的结构:
typedef struct
{
unsigned char A;
unsigned long int B;
unsigned short int C;
}
根据每种基本数据类型的对齐要求和整个结构的对齐要求,内存中的分配将是这样的:
我的问题是,只要每个结构成员与其大小自然对齐,并且我们的处理器可以在一个周期内访问(假设处理器的总线大小为32位),那么这些尾随填充字节的重要性是什么?没有对齐故障。
另外,如果我们声明一个" 2"对于这种结构,不考虑尾随字节,内存中的分配如下:
两个结构中的每个成员自然地与其大小对齐,并且可以在一个周期中访问而没有对齐错误。 那么,在这种情况下尾随字节的重要性是什么?!
答案 0 :(得分:1)
Bryan Olivier和Hans Passant的评论都是正确的。
基本上,您已经回答了自己的问题:在第二个图中,第一个和第二个数组项的成员对齐是正确的。如果编译器可以布局这样的结构,则对尾随填充字节没有重要意义。但它不能。
在C中,结构的每个实例的结构布局和大小必须相同。在第二个示例中,sizeof(array [0])为10,sizeof(array [1])为8.B2的地址仅比A2大两个,但& B1大于& A1。 / p>
它不仅仅是对齐 - 它确保了恒定的布局和尺寸,同时仍然确保对齐。即使这样,如果第一个字节对齐,它也不需要尾随填充字节,但是如果你注意到你添加了数组,那么你需要它们。
对齐+布局/尺寸+数组=>需要尾随垫。
答案 1 :(得分:1)
正如Andres所说,编译器无法为结构数组中的每个成员生成特殊布局。
例如,假设程序员已定义了具有以下类型的结构
typedef struct
{
unsigned char A;
unsigned long int B;
unsigned short int C;
} myStructureType;
然后程序员创建了这种类型的实例:
myStructureType myStructure;
如果程序员决定创建一个myStructureType
数组,编译器将按照数组元素的数量重复内存中的前一个模式,如下所示:
如果编译器忽略尾随填充字节,则内存将变为未对齐,如下所示
32位现代处理器需要两个存储器周期和一些屏蔽操作来获取B1(索引中的元素B" 1"结构数组)。但是,旧处理器会触发对齐错误。
这就是为什么尾随填充在这种情况下很重要