alignof 运算符

查询类型的对齐要求。

语法
alignof( 类型标识 )
返回 std::size_t 类型的值。

返回由类型标识所指示的类型的任何实例所要求的对齐字节数,该类型可以是完整对象类型、元素类型完整的数组类型或者到这些类型之一的引用类型。

如果类型是引用类型,那么运算符返回被引用类型的对齐要求;如果类型是数组类型,那么返回元素类型的对齐要求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 示例

#include <iostream>

struct Foo
{
int i;
float f;
char c;
};

// 注:下面的 `alignas(alignof(long double))`
// 如果需要可以简化为 `alignas(long double)`
struct alignas(alignof(long double)) Foo2
{
// Foo2 成员的定义...
};

struct Empty {};

struct alignas(64) Empty64 {};

int main()
{
std::cout << "对齐字节数" "\n"
"- char :" << alignof(char) << "\n"
"- 指针 :" << alignof(int*) << "\n"
"- Foo 类 :" << alignof(Foo) << "\n"
"- Foo2 类 :" << alignof(Foo2) << "\n"
"- 空类 :" << alignof(Empty) << "\n"
"- 带 alignas(64) 的空类:" << alignof(Empty64) << "\n";
}
可能的输出:

对齐字节数
- char1
- 指针 :8
- Foo 类 :4
- Foo2 类 :16
- 空类 :1
- 带 alignas(64) 的空类:64

alignas 说明符

指定类型或对象的对齐要求。

语法 说明
alignas( 表达式 ) 表达式 必须是求值为零或合法的对齐或扩展对齐的整型常量表达式。
alignas( 类型标识 ) 等价于 alignas(alignof(类型标识))
alignas( 包 … ) 等价于对同一说明应用多个 alignas 说明符,逐个对应于形参包的各个成员,形参包可以是类型或非类型形参包。

alignas 说明符可用于:

  • 类的声明或定义;
  • 非位域类数据成员的声明;
  • 变量声明,除了它不能应用于下列内容:
    • 函数形参;
    • catch 子句的异常形参。

这种声明所声明的对象或类型的对齐要求将等于用于该声明的所有 alignas 说明符中最严格(最大)的非零 表达式,除非这会削弱类型的自然对齐。

如果某个声明上的最严格(最大)alignas 比当它没有任何 alignas 说明符的情况下本应有的对齐更弱(即弱于其原生对齐,或弱于同一对象或类型的另一声明上的 alignas),那么程序非良构:

1
2
struct alignas(8) S {};
struct alignas(1) U { S s; }; // 错误:如果没有 alignas(1) 那么 U 的对齐将会是 8

无效的非零对齐,例如 alignas(3) 非良构。

同一声明上,比其他 alignas 弱的有效的非零对齐被忽略。

始终忽略 alignas(0)。

按 ISO C11 标准,C 语言有 _Alignas 关键词,并于头文件 <stdalign.h> 中将 alignas 定义为展开成该关键词的预处理器宏。

在 C++ 中这是关键词,且

头文件 <stdalign.h> 与 并不定义这个宏。不过它们仍定义宏常量 __alignas_is_defined。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 示例

// 每个 struct_float 类型对象都将被对齐到 alignof(float) 边界
// (通常为 4):
struct alignas(alignof(float)) struct_float
{
// 定义在此
};

// sse_t 类型的每个对象将对齐到 32 字节边界
struct alignas(32) sse_t
{
float sse_data[4];
};

// 数组 "cacheline" 将对齐到 64 字节边界
alignas(64) char cacheline[64];


#include <iostream>
int main()
{
struct default_aligned { float data[4]; } a, b, c;
sse_t x, y, z;

std::cout
<< "alignof(struct_float) = " << alignof(struct_float) << '\n'
<< "sizeof(sse_t) = " << sizeof(sse_t) << '\n'
<< "alignof(sse_t) = " << alignof(sse_t) << '\n'
<< "alignof(cacheline) = " << alignof(alignas(64) char[64]) << '\n'
<< std::hex << std::showbase
<< "&a: " << &a << '\n'
<< "&b: " << &b << '\n'
<< "&c: " << &c << '\n'
<< "&x: " << &x << '\n'
<< "&y: " << &y << '\n'
<< "&z: " << &z << '\n';
}
可能的输出:

alignof(struct_float) = 4
sizeof(sse_t) = 32
alignof(sse_t) = 32
alignof(cacheline) = 64
&a: 0x7fffcec89930
&b: 0x7fffcec89940
&c: 0x7fffcec89950
&x: 0x7fffcec89960
&y: 0x7fffcec89980
&z: 0x7fffcec899a0