为什么 char 数组的 alignof 始终为 1?

7

我正在阅读关于C++中对齐的内容,但我不确定为什么仅包含char数组成员的类的对齐方式不是数组的sizeof,而总是为1。例如:

#include <iostream>

struct Foo{char m_[16];}; // shouldn't this have a 16 byte alignment?!

int main()
{
    std::cout << sizeof(Foo) << " " << alignof(Foo);
}

在 Coliru 上查看代码

从上面的代码中可以清楚地看出,sizeof(Foo) 是 16,但是它的对齐方式是 1,可以看到代码的输出结果。

为什么在这种情况下 alignof(Foo) 是 1 呢? 请注意,如果我将 char m_[16]; 替换为像 int m_; 这样的基本类型,那么 alignof(Foo) 就会变成我所期望的,即 sizeof(int)(在我的机器上,这是 4)。

如果我只是声明一个数组 char arr[16];,那么 alignof(arr) 也将是 1。


7
@JGroven,m_ 是一个数组,而不是指针。 - chris
1
@JGroven,请阅读此内容:https://dev59.com/8m445IYBdhLWcg3wia2V#4810668。 - chris
@chris,谢谢你,我希望我能给你更多的赞同! - JGroven
1
@vsoftco 在标准中查看 - http://eel.is/c++draft/expr.alignof#3 - mpiatek
2
由于没有语言结构可以一次读取多个数组元素 - 您只能一次读取一个元素 - 数组的对齐要求只需要匹配数组元素类型的对齐要求。 - Chris Becke
显示剩余8条评论
1个回答

11

注意:数据对齐的详细说明在本文中已经解释过。如果您想了解术语的一般含义以及为什么它是一个重要问题,请阅读该文章。

C ++中将对齐定义为实现定义的整数值,表示给定对象可以分配到连续地址之间的字节数[6.11.1] Alignment

此外,对齐必须是非负的2的幂次方[6.11.4] Alignment

当我们计算结构体的对齐方式时,我们必须考虑另一条规则[6.11.5] Alignment

对齐方式从 严格的 对齐方式具有顺序。较严格的对齐方式具有更大的对齐值。满足对齐要求的地址也满足任何弱有效对齐要求。

虽然没有直接说明,但这些规则意味着结构体对齐方式必须至少与其最严格对齐的成员的对齐方式一样严格。它可能更大,但不必如此,并且通常并不是。

因此,在决定 OP 示例中结构体的对齐方式时,结构体的对齐方式必须不低于其唯一成员类型 char[16] 的对齐方式。然后通过8.3.6 [expr.alignof]

当将 alignof 应用于引用类型时,结果是所引用类型的对齐方式。将 alignof 应用于数组类型时,结果是元素类型的对齐方式

alignof(char[16]) 等于 alignof(char),由于[6.11.6] Alignment的规定,这通常为 1

(...)窄字符类型应具有最弱的对齐要求。

在此示例中:

struct Foo
{
    char c[16];
    double d;
};

double的对齐要求比char更加严格,因此alignof(Foo)等于alignof(double)


但是 Foo 不是 数组类型。它是一个包含数组的类。那么这个引用如何适用于这种情况呢?我认为需要解释一下 数组 之间的差距。 - Nawaz
@Nawaz 添加了更好的解释。 - mpiatek
“基本规则是类的对齐方式是其所有成员对齐方式的最小公倍数。”这个规则是从哪里来的呢?我认为您应该首先解释一下什么是“对齐”,它意味着什么,比如具有1、4、8等对齐方式的含义是什么?然后对于像我这样的人来说就更容易理解了。 - Nawaz
1
加上了更多的链接和文字,我认为它变得更好了。(点赞)...我现在很开心。今晚有东西可以阅读了。 :-) - Nawaz
我认为这行代码 "It could be bigger but it doesn't have to be and usually isn't." 应该更改为 "它可能会更小,但不必如此,通常也不是。", 因为如果结构体的对齐通常被视为成员的 严格 对齐的最小值,那么它就不能再大了,因为严格对齐应该是上限。 - Nawaz
显示剩余2条评论

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