45

对于任何对象类型T,是否总是sizeof(T)至少与alignof(T)?

直观上看起来是这样,因为即使您调整对象的对齐方式,例如:

struct small {
  char c;
};

在通常情况下,它们的“大小”也向上调整,以便数组中对象之间的关系在保持对齐的同时有意义(至少在我的测试中。例如:

struct alignas(16) small16 {
  char c;
};

大小和对齐方式均为 16。

4

4 回答 4

33

至少在标准 C++ 中,对于任何你可以创建一个数组(长度 > 1)的东西,这都必须是真的。如果你有

Foo arr[2];

and alignof(Foo) > sizeof(Foo), then arr[0]andarr[1]不能同时对齐。

不过,正如Zalman Stern 的示例所示,至少某些编译器允许您声明对齐大于其大小的类型,结果编译器根本不允许您声明该类型的数组。这不是符合标准的 C++(它使用类型属性,这是 GCC 扩展),但这意味着您可以alignof(T) > sizeof(T)在实践中拥有。

数组参数假定sizeof(Foo) > 0,这对于标准支持的任何类型都是正确的,但o11c 显示了一个编译器扩展破坏该保证的示例:一些编译器允许长度为 0 的数组,其中 0sizeof和 positive alignof

于 2017-09-27T21:39:14.610 回答
14
#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

所以严格来说,不,但上面的论点 re: arrays 必须被保留。

于 2017-09-27T22:07:25.513 回答
9

根据引入运算符的c++ 11 标准,定义如下(参见 5.3.3 expr.sizeof):alignofsizeof

sizeof 运算符产生其操作数的对象表示中的字节数

alignof定义是(见 5.3.6 expr.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: alignment of array elements is greater than element size

由于数组需要指定的类型符合条件:sizeof(T) >= alignof(T)

于 2017-09-27T22:22:30.703 回答
7

许多编译器允许大小为 的数组0。对齐方式与唯一元素的对齐方式相同。

(除其他外,这对于在您无法使用位域的情况下强制进行特定对齐非常有用)

于 2017-09-28T04:26:10.280 回答