为什么编译器在N个字节边界上对齐N个字节的数据类型?
我不明白为什么编译器在4个字节边界上对齐int,在2个字节边界上短路,在1个字节边界上是char。 我知道如果处理器的数据总线宽度是4字节,则需要2个存储器读取周期来读取来自不是4的倍数的地址的int。
那么,为什么编译器不能对齐4字节边界上的所有数据呢? 例如:
struct s {
char c;
short s;
};
在这里,1)为什么编译器在2字节的边界上对齐? 假设处理器可以在单个存储器读周期中读取4个字节,那么即使在字符和短字符之间没有填充,在上述情况下是不是只需要1个存储器读周期就可以读取short?
2)为什么编译器在4字节边界上不对齐?
这些对象必须适合数组。 一个数组是连续的。 因此,如果第一个元素是N字节对齐的,并且所有对象都是N个字节大,那么数组中的所有对象都必须是N字节对齐的。
所以,如果short
为2个字节,但是4个字节对齐,则禁止在数组中的所有短路之间存在2个字节的空洞。
你确实看到你的假设有点瑕疵。 我可以用26个字符构造一个struct
,并且它不会是26个字节对齐的。 它可以在任何地方开始 一个N字节类型,其对齐等于N 或N。
首先,你的前提是不正确的。 每个对象都按照一些基本对齐方式对齐。 对于一些标量对象,对齐可能与对象的数据大小相同,但也可能更小或更大。 例如,一个经典的32位体系结构(我在这里考虑i386)可能包括8字节双打和10字节长双打,都是4字节对齐。 请注意,我说的数据大小以上; 不要把它与sizeof
混淆。
对象的实际大小可能大于数据大小,因为对象的大小必须是对象的对齐的倍数。 原因是不管上下文如何,对象的对齐总是相同的。 换句话说,对象的对齐只取决于对象的类型。
因此,在结构中:
struct example1 {
type1 a;
type2 b;
};
struct example2 {
type2 b;
type1 a;
};
两个b的对齐方式是相同的。 为了能够保证这种对齐,组合类型的对齐必须是成员类型对齐的最大值。 这意味着上面的struct example1
和struct example2
具有相同的对齐方式。
对象的对齐只依赖于其类型的要求意味着类型的大小必须是其对齐的倍数。 (任何类型都可以是数组的元素类型,包括只有一个元素的数组,因此数组的大小是元素大小和元素数量的乘积,所以任何必需的填充都必须是大小的一部分的元素。)
一般来说,重新排列复合类型中的成员可能会更改复合类型的大小,但不能更改复合类型的对齐方式。 例如,以下两个结构都具有相同的对齐方式 - 即double
精度对齐 - 但第一个几乎肯定是较小的:
struct compact {
double d; // Must be at offset 0
char c1; // Will be at offset sizeof(double)
char c2; // Will be at offset sizeof(double)+sizeof(char).
};
struct bloated {
char c1; // Must be at offset 0
double d; // Will be at offset alignof(double)
char c2; // Will be at offset (alignof(double) + sizeof(double))
};
我想我找到了我的问题的答案。 可能有两个原因为什么字节在字符和短字符之间被填充,而不是在短字符之后填充。
1)一些体系结构可能有2字节的指令,只能从内存中获取2个字节。 如果是这种情况,则需要2个存储器读取周期来获取短路。
2)某些体系结构可能没有2字节指令。 即使在这种情况下,处理器也会从存储器中取出4个字节到寄存器,并屏蔽不需要的字节以获得短值。 如果该字节在char和short之间未填充,则处理器必须移位字节才能获得短值。
上述情况都可能导致性能下降。 这就是为什么字节短对齐2字节的原因。
链接地址: http://www.djcxy.com/p/54085.html上一篇: Why does compiler align N byte data types on N byte boundaries?