对象对齐与字节边界:对象是否需位于对齐要求指定的字节边界?
C++结构体数组的对齐问题
问题描述
定义如下结构体:
struct alignas(16) A { int x; }; // 对齐要求为16字节 int main() { A a[2]; }
那么a[0]和a[1]是否必须位于16字节边界上?换句话说,它们的地址低四位是否保证为0?
我原本认为答案是肯定的,但C++标准的描述让我产生了疑惑:
对象类型有对齐要求(见[basic.fundamental]、[basic.compound]),这限制了该类型对象可分配的地址。对齐是一个实现定义的整数值,表示给定对象可分配的连续地址之间的字节数。
如果按我的理解,这段条款似乎只要求a[0]和a[1]的地址差为16,地址本身可以是任意值——但这样的定义实用性很低,因此向专家求证该问题。
解答
你的理解有误,a[0]和a[1]都必须严格位于16字节的地址边界上,也就是它们的地址必须是16的倍数,低四位必然为0。
C++标准里的那段描述并没有否定对象地址必须满足对齐要求,而是从另一个角度定义“对齐”这个概念:它说的“连续可分配地址之间的字节数”,本质上等价于“地址必须是该值的整数倍”——因为如果连续可分配的地址间隔是N字节,那么第一个合法地址是X,下一个就是X+N,再下一个X+2N,以此类推,所有合法地址自然都是N的倍数。
具体到你的例子:
- 数组的第一个元素
a[0]必须满足A的16字节对齐要求,所以它的地址是16的倍数。 - 数组元素是连续布局的,
a[1]的地址等于a[0]的地址加上sizeof(A)。而因为A的对齐要求是16,编译器会自动给A补充填充字节,让sizeof(A)等于16(即便int x只占4字节,也会添加12字节的填充)。所以a[1]的地址就是a[0] + 16,自然也是16的倍数,满足对齐要求。
简单来说,任何符合C++标准的实现,都必须保证每个对象的地址满足其类型的对齐要求,数组中的每个元素也不例外。
内容的提问来源于stack exchange,提问作者john
相关产品推荐
相关产品推荐

