我现在使用共享内存。
我无法理解alignof
和alignas
。
cppreference不清楚:alignof
返回“对齐”但什么是“对齐”?为要对齐的下一个块添加的字节数?填充尺寸?堆栈溢出/博客条目也不清楚。
有人可以解释清楚alignof
吗alignas
?
我现在使用共享内存。
我无法理解alignof
和alignas
。
cppreference不清楚:alignof
返回“对齐”但什么是“对齐”?为要对齐的下一个块添加的字节数?填充尺寸?堆栈溢出/博客条目也不清楚。
有人可以解释清楚alignof
吗alignas
?
对齐是对可以存储值的第一个字节的内存位置的限制。(需要提高处理器的性能,并允许使用仅对具有特定对齐方式的数据起作用的某些指令,例如 SSE 需要对齐到 16 字节,而 AVX 需要对齐到 32 字节。)
16 对齐意味着 16 的倍数的内存地址是唯一有效的地址。
alignas
强制对齐到所需的字节数。您只能对齐 2 的幂:1、2、4、8、16、32、64、128,...
#include <cstdlib>
#include <iostream>
int main() {
alignas(16) int a[4];
alignas(1024) int b[4];
printf("%p\n", a);
printf("%p", b);
}
示例输出:
0xbfa493e0
0xbfa49000 // note how many more "zeros" now.
// binary equivalent
1011 1111 1010 0100 1001 0011 1110 0000
1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2
另一个关键字
alignof
很方便,你不能做类似的事情
int a[4];
assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error
但你可以
assert(alignof(a) == 16);
assert(alignof(b) == 1024);
请注意,实际上这比简单的“%”(模数)操作更严格。事实上,我们知道与 1024 字节对齐的东西必然与 1、2、4、8 字节对齐,但是
assert(alignof(b) == 32); // fail.
所以更准确地说,“alignof”返回 2 的最大幂来对齐某些东西。
alignof 也是提前了解基本数据类型的最小对齐要求的好方法(它可能会返回 1 表示字符,4 表示浮点数等)。
仍然合法:
alignas(alignof(float)) float SqDistance;
然后,对齐为 16 的东西将被放置在下一个可用地址上,该地址是 16 的倍数(可能存在来自上次使用的地址的隐式填充)。
对齐不是填充(尽管有时会引入填充来满足对齐要求)。它是 C++ 类型的内在属性。把它放在标准的(3.11[basic.align]
)
对象类型具有对齐要求(3.9.1、3.9.2),这些要求限制了可以分配该类型对象的地址。对齐是实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。对象类型对该类型的每个对象都有对齐要求;可以使用对齐说明符(7.6.2)请求更严格的对齐。
每种类型都有对齐要求。通常,这样可以有效地访问该类型的变量,而不必使 CPU 生成多个读/写访问以访问该数据类型的任何给定成员。此外,它还确保有效复制整个变量。alignof
将返回给定类型的对齐要求。
alignas
用于强制对数据类型进行对齐(只要alignof
所述数据类型返回的内容不那么严格)
对齐是与内存地址相关的属性。简单地说,如果地址 X 与 Z 对齐,则 x 是 Z 的倍数,即 X = Zn+0。这里重要的是 Z 始终是 2 的幂。
对齐是内存地址的一个属性,表示为数字地址模 2 的幂。例如,地址 0x0001103F 模 4 为 3。该地址被称为对齐到 4n+3,其中 4 表示选择的幂2. 地址的对齐方式取决于选择的 2 的幂。相同的地址模 8 为 7。如果地址对齐为 Xn+0,则称该地址与 X 对齐。
上述语句可在 microsoft c++ 参考中找到。
如果数据项以与其大小对齐的地址存储在内存中,则称该数据项自然对齐,否则未对齐。例如:如果一个大小为 4 字节的整数变量存储在与 4 对齐的地址中,那么我们可以说该变量是自然对齐的,即变量的地址应该是 4 的倍数。
编译器总是试图避免错位。对于简单的数据类型,地址的选择使其是变量大小(以字节为单位)的倍数。编译器还在结构的情况下适当地填充以实现自然对齐和访问。这里结构将对齐到结构中不同数据项的最大大小。例如:
struct abc
{
int a;
char b;
};
这里结构 abc 与 4 对齐,这是 int 成员的大小,明显大于 1 字节(char 成员的大小)。
对齐
此说明符用于将用户定义的类型(如结构、类等)与特定值对齐,该值是 2 的幂。
对齐
这是一种运算符,用于获取与结构或类类型对齐的值。例如:
#include <iostream>
struct alignas(16) Bar
{
int i; // 4 bytes
int n; // 4 bytes
short s; // 2 bytes
};
int main()
{
std::cout << alignof(Bar) << std::endl; // output: 16
}
要理解alignas
并且alignof
您必须知道什么是数据对齐
很好的指南https://developer.ibm.com/articles/pa-dalign//
数据对齐意味着将数据放入内存中的地址等于字大小的某个倍数。
对齐是内存地址的属性,表示为数字地址模 2 的幂。例如,地址 0x0001103F 模 4 为 3。据说该地址与 4n+3 对齐,其中 4 表示选择的 2 的幂。地址的对齐取决于选择的 2 的幂。相同的地址模 8为 7。如果地址对齐为 Xn+0,则称该地址与 X 对齐。
CPU 执行对存储在内存中的数据进行操作的指令。数据由它们在内存中的地址标识。单个基准也有大小。如果它的地址与其大小对齐,我们称它为自然对齐的数据。否则称为错位。例如,如果用于标识它的地址具有 8 字节对齐,则 8 字节浮点数据自然对齐。
好的。您了解“数据对齐”恭喜!
alignas
alignas (N)
指定将仅将数据放置在 N 的倍数的地址中
N
-以 2 的幂为模的数字
句法:
alignas( the numeric address modulo a power of 2 )
alignas( alignof(type-id) )
alignas( type-id )
alignas 说明符可应用于:
class
a / struct
/ union
or的声明或定义enumeration
;
非位域类数据成员的声明;
变量的声明,但它不能应用于以下内容:
例子:
struct alignas(256) name1 // every object of type name1 will be aligned to 256-byte boundary
{
float test[4];
};
alignas(128) char name2[128]; // the array "name2" will be aligned to 128-byte boundary
类型说明符是一种可移植的
alignas
C++ 标准方法,用于指定变量和用户定义类型的自定义对齐方式。
#include <iostream>
struct alignas(16) Bar
{
int i; // 4 bytes
int n; // 4 bytes
alignas(4) char arr[3];
short s; // 2 bytes
};
int main()
{
std::cout << alignof(Bar) << std::endl;
}
当遇到多个 alignas 说明符时,编译器将选择最严格的一个(具有最大值的那个)。
output: 16
alignas
不能用于为类型提供比没有此声明时的类型更小的对齐方式
alignof
句法:
alignof( type-id )
返回类型的值
std::size_t
相同的定义有sizeof( type-id )
sizeof
和有什么区别alignof
?
struct MyStruct
{
int x;
double y;
char z;
};
main()
{
std::cout << "The sizeof(MyStruct): " << sizeof(MyStruct) << std::endl;
std::cout << "The alignof(MyStruct): " << alignof(MyStruct) << std::endl;
}
output:
The sizeof(MyStruct): 24
The alignof(MyStruct): 8
结构填充问题
结构填充是 C 中的一个概念,它在内存地址之间添加一个或多个空字节以对齐内存中的数据
更多信息:C++ 中的结构填充
结果是一个类型为 的常量表达式
std::size_t
,也就是说,它可以在编译时求值。