首页 > Coding > C++ 内存对齐

C++ 内存对齐

2021年1月8日 发表评论 阅读评论

如下两个结构体 A B ,他们的实例的大小相同吗?

两个 char 共占两个字节, 一个 int 占4个字节, 所以两个结构体都是 6个字节。但事实并非如此,在大部分计算机中,他们都不会只占 6 个字节。这涉及到 内存对齐
需知,计算机访问内存的方式,并不是一个字节一个字节访问的,而是以字长(word size)为单位来进行访问的。32位计算机的字长为 4 字节, 64位计算机的字节为 8 字节。而所谓内存对齐, 就是将变量调整至字长的倍数的位置存放,以方便计算机访问
上面两个结构体在内存中的布局最有可能是这个样子的:(这里说 最有可能 是因为具体的布局要视计算机而定)


我们使用一段代码来验证:

结果如下:

A 中,c_1 i 共占一个字,c_2 占一个字。这种将多个变量放入一个字中的动作,叫作 packing 。 而组成一个字时,补充不足的部分,叫 padding
如何知道某种类型的变量要对齐到哪个位置呢?它取决于一个类型的 alignment 如 int 类型的alignment 为4, 那么int 类型变量的地址必定为 4 的倍数。

alignof alignment

C++11 引入了 alignof 运算符。它类似于 sizeof 运算符, 返回一个类型的 alignment
我们来看一些数据类型的 alignment

对于内置类型, 其 alignment 就是其 size 。 对于复杂类型, 其 alignment 为其所有成员的 alignment 的最大值,其size 为完成对齐后的内存大小。如上,我们得知 A B 的alignment 均为4 (即 int 的 alignment 。 那么他们的实例的首地址一定是4的倍数。

alignas

以上我们看到的都是默认的alignment. 而很多语言允许用户控制alignment, 如 Rust, Assembly, 当然也包括 C/C++ .
C++11 提供了 alignas 关键字来完成这种控制。alignas 可以修饰 class struct union enumeration 或其非位域(non-bitfield)的成员 。 alignas(N) type 表示将 type 对齐到 N 字节。其中 N 必须为 2 的 n 次幂, 且不小于 alignof(type)
如下代码中,我们令 A 以 32 字节对齐, B::c_2 以 8 字节对齐。

结果就是: A 将 padding 至 32 字节大小, 而 B.c_2 将对齐到第8字节上。

 

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.