6

结构的每个成员的类型通常具有默认对齐方式,即每个结构成员在预先确定的边界上对齐。出于这个原因,填充是在以下 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 */
};

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

4

3 回答 3

9

在许多架构上,从主内存到主内存的对齐读取和写入比它们的未对齐对应物快得多。

于 2012-06-19T10:55:08.777 回答
9

未对齐的读取和写入通常需要 CPU 从内存中获取两个相邻的字(而不仅仅是一个),并应用一些额外的按位运算才能正确执行指定的操作。

一些架构,比如 x86 会以性能为代价来实现。其他架构(最著名的是 ARM)要么引发异常(通常导致SIGBUS用户进程发出信号),要么甚至将地址“四舍五入”到最近的边界,这可能导致一些非常讨厌的错误。

于 2012-06-19T11:00:59.197 回答
2

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

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

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

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

通常可以使用编译器/pragma 指令更改结构填充,这可能会否定您的示例中指定的手动填充的需要,但是对于每个编译器来说这通常是不同的。

于 2012-06-19T11:01:53.797 回答