C++ 字节对齐

原因

  32 位处理器每次最多可以处理 32 位数据(也就是 CPU 的数据线是 32 位的,这里可以了解地址线和数据线),但是许多数据只需要 8位,16 位。比如文本处理常用的 ASCII 码,只需要 8 位,即使用 Unicode,也只要16位,所以 32 位处理器基本都具备处理更短位数数据的能力,也就是并非每次都一定要取 4 个字节的数据。实际上,计算机并非总是逐字节大小读写内存,而是以 2、4 或 8 的倍数的字节块来读写内存,有时也会只取一个字节。需要注意的是,只有位于 0x00、0x02、0x04、··· 的可以被 2 整除的位置上才会采取以 2 的倍数的字节块读写内存,只有位于 0x00、0x04、0x08、··· 位置上才会采取 4 的倍数的字节快读写内存,同理有 8 的倍数的字节块
  计算机在取数据的时候,偏向于取数据次数较少的取数方案,如一个 int 数据位于 0x02 上,那么计算机会先从 0x02-0x03 上取一个 short,然后从 0x04-0x05 上一个 short,两个拼接一起就是一个 int,需要取数 2 次。如果在 0x03 处,那么会先从 0x03 上取一个 char,然后从 0x04-0x05 上取一个 short,再从 0x06 上取一个 char,拼接成一个 int,需要取数 3 次。
  如果 int 正好位于 0x00 或 0x04 等位置,那么它只需要取数一次即可。因此,常常希望这些基本类型能够位于对齐的位置上,方便一次取出。

一些概念

自身对齐值

基本类型的自身对齐值

为指定平台上基本类型的长度。对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。

结构体或类的自身对齐值

其成员中自身对齐值最大的那个值。

指定对齐值

#pragma pack (value) 时的指定对齐值 value。

有效对齐值

自身对齐值和指定对齐值的较小值。

对齐原则

基本数据类型对齐原则

地址是长度的整数倍。

数组的对齐原则

按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。

联合的对齐原则

按其包含的长度最大的数据类型对齐。

结构体的对齐原则

每个成员都要对齐,编译器可能需要在结构体字段的分配中插入间隙,以保证每个结构元素都满足它的对齐要求。第一个数据变量的起始地址就是数据结构的起始地址结构体本身也要根据自身的有效对齐值圆整(就是结构体总长度需要是结构体有效对齐值的整数倍),此时可能需要在结构末尾填充一些空间,以满足结构体整体的对齐—-向结构体元素中最大的元素对齐。简而言之就是 (1)每个成员必须对齐,其地址可以被自身长度整除;(2)对于第一个元素,其地址应该可以被整个结构体的对齐字节数整除;(3)整个结构体是圆整的,总长度为最大长度数据成员的整数倍

实例

下面的结构体的 sizeof 是多少?

struct test
{
    char a;
    int b;
    short c;
    char d;
};

正确答案:12
如果首地址是 0x00,在内存中的图示可能是这样的:

a
bbbb
ccd
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中的字节对齐(内存对齐)是指在分配内存时,将变量或结构体的起始地址对齐到特定的字节边界。这样做有助于提高内存访问的效率和性能。字节对齐的规则可以通过编译器选项或特定的关键字进行控制。 以下是关于C++字节对齐的一些重要概念和规则: 1. 默认对齐: - 编译器会使用默认的对齐规则来分配内存。通常,默认对齐值是被编译器设置的,一般为结构体成员中最大的对齐值。 2. 对齐值: - 对齐值是指要求变量或结构体的起始地址必须是该值的倍数。常见的对齐值有1、2、4、8等。 3. 对齐修饰符: - C++11引入了对齐修饰符 `alignas`,允许开发者显式地指定变量或结构体的对齐值。 4. 结构体字节对齐: - 结构体的字节对齐规则是,结构体的起始地址必须是其成员中最大对齐值的倍数。 - 编译器会在结构体成员之间插入填充字节,以保证对齐要求。 5. 类对象字节对齐: - 类对象的字节对齐规则与结构体类似,但还受到继承关系的影响。 - 派生类的起始地址必须满足其成员的对齐要求,并且满足其基类中最大对齐值的倍数。 为了控制字节对齐,可以使用编译器提供的特定选项(如`#pragma pack`)或关键字(如`alignas`)。具体的字节对齐规则和选项可能因编译器和平台而异,因此在编写代码时最好参考特定编译器的文档。正确的字节对齐可以提高内存访问性能,并确保与其他代码或外部系统的兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值