浮点数组是否始终与16字节边界对齐?

时间:2013-11-20 16:27:26

标签: c++ c memory-management

我的理解是,如果要对齐数组,必须明确指定数组的对齐方式。

但是,我声明的浮点数组似乎总是与16字节对齐。

float *ptr1 = new float[1];
cout<<"ptr1: "<<ptr1<<endl;
float *ptr2 = new float[3];
cout<<"ptr2: "<<ptr2<<endl;
float arr1[7];
cout<<"arr1: "<<arr1<<endl;
float arr2[9] __attribute__((aligned(2)));
cout<<"arr2: "<<arr2<<endl;

这是输出

ptr1: 0x13dc010
ptr2: 0x13dc030
arr1: 0x7fff874885c0
arr2: 0x7fff87488590

这有什么理由吗?我正在使用gcc 4.6.3

但是,如果它是指向浮点位置或静态分配的指针,我看不到它

static float arr3[9] __attribute__((aligned(2)));
cout<<"arr3: "<<arr3<<endl;
float *x;
cout<<"x: "<<x<<endl;

输出:

arr3: 0x4030b2
x: 0x7fff8c7dd9e8

此代码在x64上运行。

3 个答案:

答案 0 :(得分:4)

对齐要求由每个编译器确定,受硬件要求的影响。

C和C ++语言讨论了类型的对齐,但它们没有强加任何特定的要求(例如,结构的对齐至少是其任何成员的对齐)。有效的实现可以允许所有数据类型进行字节对齐,或者可能要求每个标量类型与其自己的大小对齐(后者更常见)。中间对齐是可能的,例如在4字节边界上对齐8字节类型。

特别是在x86上,将标量与其大小对齐可以提高访问效率,但是错位访问仍然可以正常工作,但速度要慢一点。

float数组的必需对齐方式与单个float对象所需的对齐方式相同。如果float是4个字节,那么该对齐不能超过4个字节,因为数组之间没有间隙。

特定编译器可能会选择对数组对象进行更严格的对齐,就像您(可能)看到的那样,如果它能够更有效地访问这些对象。

如果通过调用new来实现malloc运算符,则所有new - 分配的对象将具有足够严格的对齐任何类型。

如果float数组始终与16字节边界对齐,那是因为编译器选择以这种方式分配它们,而不是因为语言需要它。另一方面,如果使用别名强制float数组为4字节对齐(假设为sizeof (float) == 4),则对该数组及其元素的访问仍应正常工作。

顺便提一下,当我在x86_64系统上运行你的代码(在main程序中包装它之后)后,我得到的结果与你的类似。当我在x86系统上运行它时,我得到:

ptr1: 0x9e34008
ptr2: 0x9e34018
arr1: 0xbfefa160
arr2: 0xbfefa17c

我在两个系统上使用Linux下的gcc。

因此,您问题的直截了当的答案是否定的,float数组并不总是与16字节边界对齐。

但在大多数情况下,没有特别理由让你关心。除非您使用别名技巧(将某些声明类型的对象视为另一种类型),否则编译器将始终为每个对象提供正确访问所需的对齐

答案 1 :(得分:1)

我不确定我是否完全理解这个问题,但如果你想要更大的尺寸,我建议使用“double”类型而不是“float”。 “Float”的大小限制通常为4个字节(约7位),而“double”的大小限制通常为8个字节(约15个数字)。

编辑:对不起,我误解了这个问题

答案 2 :(得分:0)

这取决于平台的最严格的基本类型对齐要求,如long double,这是我的Debian 64系统需要的16字节对齐。 堆栈帧对齐也可能受此影响。