结构的每个成员的类型通常具有默认对齐,即,每个结构成员在预定边界上对齐。 因此,填充是在以下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 */
};
应该保留对齐的(实际)原因是什么?
答案 0 :(得分:9)
在许多架构中,与主内存对齐的读写操作比未对齐的内存快得多。
答案 1 :(得分:8)
未对齐的读写通常要求CPU从存储器中取出两个相邻的字(而不是仅仅一个)并应用一些额外的逐位算术以便正确执行指定的操作。
某些体系结构(如x86)将以性能成本实现。其他体系结构(最值得注意的是ARM)会引发异常(通常会导致用户进程发出SIGBUS
信号),甚至会将地址“舍入”到最近的边界,这可能会导致一些非常讨厌的错误。 / p>
答案 2 :(得分:2)
通常,结构在依赖于处理器的对齐上对齐,以便使用处理器的“自然”寄存器大小尽可能快地访问它们。
对于32位处理器,它是4字节(或32位),对于64位处理器,它是8字节。
如果你尝试访问(比如说)一个int,如果它没有在正确的边界上对齐,那么某些(非x86)处理器会产生错误。
不同设备之间的通信是保持对齐的实际原因。使用默认对齐时,此结构的长度为24个字节,而在64位处理器上,则为48个字节,除第一个之外的其他项目都不在同一位置。
通常可以使用编译器/编译指示更改结构填充,这可能会取消对示例中指定的手动填充的需要,但对于每个编译器通常都是不同的。