静态字符数组的对齐保证

6
我想了解静态分配的char数组的对齐保证。查看其他SO问题,我发现一些关于动态分配的char数组的问题。对于静态分配的char数组,它们是否对齐,以便我可以将任何类型放置到其中(只要足够大)?还是这只适用于动态分配的数组?
char buff[sizeof(T)];
T * pT = (T*) buff;
new(pT) T(); // well defined?
...
pT->~T();

如果不行,我该如何解决这个问题?

我相信C++11可以保证这一点,而C++03则不能。我会让其他人发布一个真正带有标准引用的答案。 - K-ballo
@K-ballo: 我不认为C++11保证了这一点。它添加了alignas来实现这个目的。 - Nawaz
@Nawaz:这是我从 3.11/6 [basic.align] 中的理解,你觉得呢?我理解错了吗? - K-ballo
@K-ballo: 我很确定你搞错了。3.11/6说char类型具有最弱的对齐方式,而3.11/5则说更严格的对齐方式(具有更大的对齐值)满足较弱的对齐方式(具有较小的对齐值),而不是反过来。问题在于只要注意对齐方式,就可以将char类型用于对齐内存区域。参考3.11/6注释中提到的7.6.2(对齐说明符)来了解如何做到这一点的一种方法。另一种方法是过度分配char数组,在数组内部使用适当对齐的偏移指针。 - James Caccese
3个回答

11
在C++11中,正确的做法是这样的:
char alignas(T) buff[sizeof(T)]; //Notice 'alignas' as
T * pT = (T*) buff;
new(pT) T(); // well defined!

请注意使用alignas的方法。

如果T是模板参数,则最好使用std::alignment_of类模板:

char alignas(std::alignment_of<T>::value) buff[sizeof(T)]; 

同时请注意,传递给 alignas 的参数可以是一个 正整数值 或者 类型。因此,以下两种写法是等价的:

char alignas(T)          buff[sizeof(T)];
char alignas(alignof(T))  buff[sizeof(T)]; //same as above

第二种方法使用alignof,它返回一个类型为std::size_t的整数值。

3
“C+++”,那将会是一门不错的编程语言!:P - K-ballo
@DavidHammen:哎呀……我没注意到。 - Nawaz
@Nawaz,我认为alignas(T)与alignas(sizeof(T))不同。例如对于结构体,对齐方式是最严格对齐成员的对齐方式,对于任何具有多个成员的结构体,其大小都小于结构体的大小。 - AProgrammer
@AProgrammer:是打错字了,我是指 alignas(alignof(T)) 而不是 alignas(sizeof(T)) - Nawaz
1
@user1095108:std::alignment_of通常在模板内使用,此时如果模板参数T是数组类型,则std::alignment_of返回元素类型的对齐要求。alignof则不会这样做。 - Nawaz
显示剩余2条评论

8
如果您想保证静态字符数组的对齐,可以使用联合技巧。
union
{
    char buff[sizeof(T)];
    uint64_t dummy;
};

这里将保证联合体中最大元素的对齐方式。当然,你应该将这个不好看的代码封装成一个漂亮的类。
编辑:更好的答案是使用boost::aligned_storage或者C++11中的alignas。

1

不,静态分配的数组对齐到sizeof(element_type)字节--对于char类型,它是1个字节,这基本上保证了没有对齐。


二维数组,例如char a[M][N],是否适用相同的规则? - Michał Górny
@MichałGórny 我相信是这样的,因为它们实际上只是一维的。 - user529758

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接