例如,如果我声明一个长变量,我可以假设它总是在“sizeof(long)”边界上对齐吗?Microsoft Visual C++ 在线帮助这么说,但这是标准行为吗?
更多信息:
一种。可以显式地创建一个未对齐的整数 (*bar):
字符富[5]
int * bar = (int *)(&foo[1]);
湾。显然,#pragma pack() 只影响结构、类和联合。
C。MSVC 文档指出 POD 类型与其各自的大小对齐(但它始终还是默认情况下,它是标准行为,我不知道)
例如,如果我声明一个长变量,我可以假设它总是在“sizeof(long)”边界上对齐吗?Microsoft Visual C++ 在线帮助这么说,但这是标准行为吗?
更多信息:
一种。可以显式地创建一个未对齐的整数 (*bar):
字符富[5]
int * bar = (int *)(&foo[1]);
湾。显然,#pragma pack() 只影响结构、类和联合。
C。MSVC 文档指出 POD 类型与其各自的大小对齐(但它始终还是默认情况下,它是标准行为,我不知道)
正如其他人所提到的,这不是标准的一部分,而是留给编译器来实现,因为它认为适合所讨论的处理器。例如,VC 可以轻松地为 ARM 处理器实现与 x86 处理器不同的对齐要求。
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 处理器会抛出一个处理器异常,该异常会被操作系统捕获。然后,操作系统将检查指令,然后执行处理未对齐数据所需的工作。然后继续执行。该__unaligned
关键字可以在 VC 中用于标记非 x86 程序(即 CE)的未对齐访问。
默认情况下,是的。但是,可以通过 pack() #pragma 更改它。
我不相信 C++ 标准在这方面有任何要求,并将其留给实现。
C 和 C++ 不要求任何类型的对齐。但是 x86 强烈倾向于自然对齐,并且大多数其他 CPU 体系结构都需要自然对齐,编译器通常会尽最大努力让 CPU 满意。所以在实践中你不会看到编译器生成未对齐的数据,除非你真的扭曲它的手臂。
是的,所有类型总是至少与它们的对齐要求对齐。
不然怎么可能?
但请注意 sizeof() 类型与它的对齐方式不同。
您可以使用以下宏来确定类型的对齐要求:
#define ALIGNMENT_OF( t ) offsetof( struct { char x; t test; }, test )
取决于编译器、编译指示和优化级别。使用现代编译器,您还可以选择时间或空间优化,这也可以改变类型的对齐方式。
一般来说,这是因为读取/写入它会更快。但几乎每个编译器都有一个开关来关闭它。在 gcc 中它的 -malign-???。对于聚合,它们通常根据内部每个元素的对齐要求进行对齐和调整大小。