POD类型是否始终对齐?
例如,如果声明一个long变量,是否可以假定它始终在" sizeof(long)"边界上对齐? Microsoft Visual C ++联机帮助说是这样,但这是标准行为吗?
一些更多的信息:
一种。可以显式创建未对齐的整数(* bar):
char foo[5] int * bar = (int *)(&foo[1]);
b。显然,#pragma pack()仅影响结构,类和联合。
C。 MSVC文档指出POD类型与它们各自的大小对齐(但是,它始终是默认情况还是默认情况,它是标准行为,我不知道)
解决方案
是的,所有类型始终都至少符合其对齐要求。
怎么会这样呢?
但请注意,类型的sizeof()与对齐方式不同。
我们可以使用以下宏来确定类型的对齐要求:
#define ALIGNMENT_OF( t ) offsetof( struct { char x; t test; }, test )
默认情况下,是。但是,可以通过pack()#pragma进行更改。
我不认为C ++标准在这方面有任何要求,而将其留待实施。
取决于编译器,编译指示和优化级别。使用现代编译器,我们还可以选择时间或者空间优化,这也可能会改变类型的对齐方式。
通常,这是因为对它的读/写速度更快。但是几乎每个编译器都有一个开关来关闭它。在gcc中,它是-malign-???。对于聚集体,它们通常根据其中每个元素的对齐要求进行对齐和调整大小。
正如其他人提到的那样,这不是标准的一部分,而是由编译器来实现,因为它认为适合所讨论的处理器。例如,VC可以轻松实现与x86处理器不同的ARM处理器对齐要求。
Microsoft VC实现基本上所谓的自然对齐,直到#pragma pack指令或者/ Zp命令行选项指定的大小为止。这意味着,例如,任何大小小于或者等于8个字节的POD类型都将根据其大小对齐。较大的将在8字节边界上对齐。
如果控制不同处理器和编译器的对齐很重要,那么可以使用1的打包大小并填充结构。
#pragma pack(push) #pragma pack(1) struct Example { short data1; // offset 0 short padding1; // offset 2 long data2; // offset 4 }; #pragma pack(pop)
在此代码中,存在padding1变量只是为了确保data2自然对齐。
答案:
是的,这很容易导致数据未对齐。在x86处理器上,这实际上并没有多大伤害。在其他处理器上,这可能导致崩溃或者执行速度非常慢。例如,Alpha处理器将抛出处理器异常,该异常将被OS捕获。然后,操作系统将检查指令,然后进行处理未对齐数据所需的工作。然后执行继续。可以在VC中使用__unaligned
关键字来标记非x86程序(即,对于CE)的未对齐访问。
C和C ++不要求任何对齐方式。但是x86强烈建议采用自然对齐方式,大多数其他CPU体系结构都要求采用自然对齐方式,并且编译器通常会尽最大努力使CPU保持满意状态。因此在实践中,除非我们真的扭曲了编译器,否则我们不会看到编译器生成未对齐的数据。