对于任何对象类型 T
,sizeof(T)
大小至少与 alignof(T)
相同吗?
直观上看似乎是这样的,因为即使调整对象的对齐方式:
struct small {
char c;
};
在正常情况下,它们的“大小”也会向上调整,以使数组中对象之间的关系保持一致,同时保持对齐(至少在我的测试中)。例如:
struct alignas(16) small16 {
char c;
};
这个元素的大小和对齐方式均为16。
对于任何对象类型 T
,sizeof(T)
大小至少与 alignof(T)
相同吗?
直观上看似乎是这样的,因为即使调整对象的对齐方式:
struct small {
char c;
};
在正常情况下,它们的“大小”也会向上调整,以使数组中对象之间的关系保持一致,同时保持对齐(至少在我的测试中)。例如:
struct alignas(16) small16 {
char c;
};
这个元素的大小和对齐方式均为16。
至少在标准C++中,对于任何您可以制作长度大于1的数组的内容,这都是正确的。如果您有
Foo arr[2];
如果 alignof(Foo) > sizeof(Foo)
,那么 arr[0]
和 arr[1]
不能同时对齐。
然而,正如 Zalman Stern 的示例 所示,至少一些编译器允许您声明一个具有大于其大小的对齐方式的类型,结果是编译器不会让您声明该类型的数组。这不是符合标准的 C++(它使用类型属性,这是 GCC 扩展),但它意味着您可以在实践中拥有 alignof(T) > sizeof(T)
。
数组参数假设 sizeof(Foo) > 0
,这对于标准支持的任何类型都是正确的,但是 o11c 显示了 编译器扩展破坏了该保证:某些编译器允许长度为零、sizeof
为零且 alignof
为正数的数组。
sizeof(Foo[2]) > 2*sizeof(Foo)
是被允许的,这将会打破你的论点。不过我不确定是否应该相信他。 - BeeOnRopesizeof
不是很有用。 - curiousguy__attribute__ ((aligned (64)))
。类型属性是GCC扩展,而不是C或C++标准的一部分。我进行了编辑以澄清 - 希望这样可以。 - sleske#include <iostream>
typedef double foo __attribute__ ((aligned (64)));
alignas(64) double bar;
double baz __attribute__ ((aligned (64)));
int main(int argc, char *argv[]) {
std::cout << "foo sizeof: " << sizeof(foo) << " alignof: " << alignof(foo) << "\n";
std::cout << "bar sizeof: " << sizeof(bar) << " alignof: " << alignof(decltype(bar)) << "\n";
std::cout << "baz sizeof: " << sizeof(baz) << " alignof: " << alignof(decltype(baz)) << "\n";
}
使用以下命令进行编译:
clang++ -std=c++11 alignof_test.cpp -o alignof_test && ./alignof_test
输出:
foo sizeof: 8 alignof: 64
bar sizeof: 8 alignof: 8
baz sizeof: 8 alignof: 8
严格来说,不可以,但是上述关于数组的论点必须被保留。
foo arr[2]; std :: cout << sizeof(arr)<<“\ n”;
- Andrew Henlefoo
的对象,则它将保持 64 字节的 alignof
。有趣的是,如果您将 aligned
属性附加到 typedef 并使用 typedef,与直接将其附加到变量声明相比,它会以不同的方式与 alignof
交互。 - user2357112__attribute__
是GCC的扩展。我还没有找到使用 alignof
能够获得相同结果的方法;我可以创建一个对象,使其 alignof(obj) > sizeof(obj)
,但无法创建该类型。 - user2357112alignof
操作符,sizeof
的定义如下(参见5.3.3表达式.sizeof):
而sizeof操作符返回其操作数的对象表示中所占用的字节数。
alignof
的定义为(参见5.3.6表达式.alignof):
由于一个 alignof 表达式返回其操作数类型的对齐要求。
alignof
的定义规定了可能由用户制定的需求,而不是语言规范,因此我们可以操纵编译器:typedef uint32_t __attribute__ ((aligned (64))) aligned_uint32_t;
std::cout << sizeof(aligned_uint32_t) << " -> " << alignof(aligned_uint32_t);
// Output: 4 -> 64
编辑
正如其他人指出的那样,这种类型不能用于数组中,例如尝试编译以下内容:
aligned_uint32_t arr[2];
出现错误:error: 数组元素的对齐方式大于元素大小
由于数组要求指定的类型符合以下条件:sizeof(T) >= alignof(T)
aligned_uinit32_t
并不是一种类型,尽管您给它命名的方式是这样的。它声明了一个具有不同对齐方式的堆栈变量。我知道在这种情况下,对齐方式是您要求的,并且sizeof
不会改变。问题是是否可以在使用时使该行为成为一种类型。 - BeeOnRope0
的数组。对齐方式与唯一元素的对齐方式相同。
sizeof
(分别为12和I * 200)比alignof
(分别为1和I)大,其中I是sizeof(I)。 - BeeOnRopefloat
占用 4 个字节,sizeof(float)
返回值为 4,但系统体系结构要求float
必须位于 8 字节边界上”,那么会发生什么?直接说,我认为这意味着float
数组会出现错误。 - Andrew Henlesizeof(T) == alignof(T)
并不成立。例如,struct S { char a,b; };
通常大小为2,对齐方式为1,这是显而易见的。我的问题是关于>=
而不是==
... - BeeOnRopesizeof 16
。这就是为什么我问@tadman,是否有一个平台的sizeof(long double)
小于alignof(long double)
,因为这似乎不可能是一种合规的实现! - BeeOnRope