为什么“任何K个字节的原始对象必须具有K的倍数的地址"? [英] Why "any primitive object of K bytes must have an address that is a multiple of K"?

查看:111
本文介绍了为什么“任何K个字节的原始对象必须具有K的倍数的地址"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

计算机系统:程序员的观点说

Computer Systems: a Programmer's Perspective says

x86-64硬件将正确运行,而不管是否对齐 数据.但是,英特尔建议对数据进行对齐以改善内存 系统性能.它们的对齐规则基于原理 任何K个字节的原始对象必须具有一个地址,该地址是 K的倍数.我们可以看到,该规则导致以下情况 对齐方式:

The x86-64 hardware will work correctly regardless of the alignment of data. However, Intel recommends that data be aligned to improve memory system performance. Their alignment rule is based on the principle that any primitive object of K bytes must have an address that is a multiple of K. We can see that this rule leads to the following alignments:

K Types
1 char
2 short
4 int, float
8 long, double, char *

为什么任何K个字节的原始对象都必须具有K的倍数的地址"?

Why is it that "any primitive object of K bytes must have an address that is a multiple of K"?

对齐"的定义是什么?

在x86-64机器上,

On a x86-64 machine,

  • 如果对象具有K个字节(例如K = 2(例如short)或K = 4(例如int或float)),则任何K个字节的原始对象的地址都必须是整数倍"表示该对象必须具有K的倍数的地址.但是,该对象不是对齐的,只要它的存储空间完全落在两个地址之间,该地址是8的两个连续倍数,则该值要小一些严格的要求,而不是对象必须具有K的倍数的地址?

  • if an object has K bytes (such as K=2 (e.g. short) or K=4 (e.g. int, or float)), "any primitive object of K bytes must have an address that is a multiple of K" means that such an object must have an address that is a multiple of K. But isn't the object aligned, as long as its storage space falls completely between two addresses which are two consecutive multiples of 8, which is a less strict requirement than that the object must have an address that is a multiple of K?

如果对象的K小于8但不等于1、2或4,是否仍然适用任何K个字节的原始对象的地址必须是K的倍数"?例如,如果K = 3、5、6或7?

If the K of an object is smaller than 8 but not equal to 1, 2 or 4, does "any primitive object of K bytes must have an address that is a multiple of K" still apply? For example if K=3,5,6, or 7?

在具有32位地址的X86机器上,

On a X86 machine, which has 32-bit addresses,

  • 什么是对齐规则,并且任何K字节的原始对象必须具有K的倍数的地址"是否仍然适用?

谢谢.

推荐答案

由于这也是在 C 中进行了标记;需要注意的是,架构不仅会做出这些决定,而且编译器也会做出决定. C编译器通常具有自己的对齐规则,这些规则大多遵循体系结构的必需或首选对齐方式-尤其是在优化 speed 时.而您最需要担心的是编译器的需求,而不是体系结构的需求.

Since this was tagged in C as well; do note that not only does the architecture make these decisions, but so do compilers. The C compiler often has its own alignment rules that mostly follow either the required or the preferred alignment of the architecture - especially when optimizing for speed. And the compiler's requirements are what you you need to worry about the most time, not the architecture requirement.

即使处理器支持不对齐的访问,它可能也具有 C编译器可以利用的多字节对象的首选对齐方式.例如,允许编译器知道任何int将驻留在其中,因此任何int *指针将始终指向-一个可被4整除的地址.

Even if the processor supports unaligned accesses, it might have a preferred alignment for multibyte objects that the C compiler can exploit. For example a compiler is allowed to know that a any int will reside at, and therefore any int * pointer will always point to - an address divisible by 4.

现在有些人说,由于x86-64支持不对齐访问,因此他们可以创建int *指针,该指针指向不被4整除的地址,并且一切正常.

Now there are people who say that since x86-64 supports unaligned acccess, they can make an int * pointer that points to an address not divisible by 4 and things will work fine.

他们错了.

x86-64指令集中有 条指令,需要对齐. IE. 无论对齐如何都将正确工作"意味着这些指令根据规范,在获得未对齐访问权限时也能正确工作",它们会引发异常,这会杀死您的过程.拥有这些功能的原因是,与可以处理未对齐数据的版本相比,它们可以更快,所需的硅更少.

There are some instructions in the x86-64 instruction set that require alignment. I.e. the "will work correctly regardless of alignment" means that these instructions too work "correctly, according to the specification, when given an unaligned access" - they raise an exception that would kill your process. The reason for having these is that they can be so much faster and require less silicon to implement than the versions that can deal with unaligned data.

当允许使用这些指令时,编译器会确切地知道 !每当发现int *被取消引用时,它知道,它可以使用一条指令,该指令要求将操作数对​​齐4个字节,这样才能更有效.

And the compiler knows exactly when it is allowed to use these instructions! Whenever it sees an int * being dereferenced it knows that it can use an instruction that requires the operand be aligned at 4 bytes, should it be more effective.

对于OP遇到无论如何在x86-64上都应该还不错"的C代码问题,请参见此问题:

See this question for a case where OP run into problem with C code that "should have been fine on x86-64 anyway": C undefined behavior. Strict aliasing rule, or incorrect alignment?

对于x86-32,C编译器中double s的对齐要求通常为 4 ,因为需要在堆栈上传递双精度数,并且堆栈以4而不是8字节的增量增长.

As for x86-32, the alignment requirement for doubles is generally 4 in C compilers because doubles need to be passed on stack and stack grows in 4 not 8 byte increments.

最后:

如果对象的K小于8但不等于1、2或4,是否仍然适用任何K个字节的原始对象的地址必须是K的倍数"?例如,如果K = 3、5、6或7?

If the K of an object is smaller than 8 but not equal to 1, 2 or 4, does "any primitive object of K bytes must have an address that is a multiple of K" still apply? For example if K=3,5,6, or 7?

在x86中,没有原始对象具有K <-{3,5,6,7}.

There are no primitive objects with K<-{3,5,6,7} in x86.

C标准的立场是,对齐方式只能是2的幂,并且数组中没有间隙.因此,需要将具有这种尺寸的对象向上填充到其对齐要求,或者其对齐要求必须为1.

The C standard's stance is that an alignment can only be a power of 2, and there are no gaps in arrays. Therefore an object with such a size would need to be padded upwards to its alignment requirement, or its alignment requirement must be 1.

这篇关于为什么“任何K个字节的原始对象必须具有K的倍数的地址"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆