为什么赞成数据结构对齐?

结构的每个成员的类型通常具有默认对齐,即每个结构成员在预定边界上对齐。 因此,填充是在以下wiki示例中执行的:

struct MixedData { char Data1; short Data2; int Data3; char Data4; }; struct MixedData /* After compilation in 32-bit x86 machine */ { char Data1; /* 1 byte */ /* 1 byte for the following 'short' to be aligned on a 2 byte boundary assuming that the address where structure begins is an even number */ char Padding1[1]; short Data2; /* 2 bytes */ int Data3; /* 4 bytes - largest structure member */ char Data4; /* 1 byte */ char Padding2[3]; /* 3 bytes to make total size of the structure 12 bytes */ }; 

应该保留对齐的(实际)原因是什么?

未对齐的读取和写入通常要求CPU从存储器(而不是仅仅一个)中获取两个相邻的字,并应用一些额外的逐位算术以正确执行指定的操作。

某些体系结构(如x86)将以性能成本实现。 其他架构(最着名的是ARM)将引发exception(通常导致用户进程的SIGBUS信号)或甚至将地址“舍入”到最近的边界,这可能导致一些非常讨厌的错误。

在许多体系结构中,与主存储器对齐的读取和写入比未对齐的对应物快得多。

通常,结构在依赖于处理器的对齐上对齐,以使用处理器的“自然”寄存器大小尽可能快地访问它们。

对于32位处理器,它是4字节(或32位),对于64位处理器,它是8字节。

如果您尝试访问(例如)一个int(如果它没有在正确的边界上对齐),则某些(非x86)处理器将生成错误。

不同设备之间的通信是保持对齐的实际原因。 使用默认对齐时,此结构将长度为24个字节,而在64位处理器上,它将为48个字节,除第一个之外的项目不在同一位置。

通常可以使用编译器/编译指示更改结构填充,这可能会取消对示例中指定的手动填充的需要,但对于每个编译器而言通常是不同的。