内存对齐规则

前言

我们知道,各种数据类型都是有大小的,常见的数据类型大小:

基本整数类型
char:1字节。用于存储单个字符,如字母、数字或标点符号。
short:通常为2字节。是int类型的一个较短变体,用于存储较小的整数。
int:通常为4字节。是基本的整数类型,用于存储整数。
long:通常为4字节(在32位系统上)或8字节(在64位系统上)。是int类型的一个较长变体,用于存储更大的整数。
long long:通常为8字节。是更长的整数类型,用于存储非常大的整数。
浮点数类型
float:通常为4字节。是单精度浮点数类型,用于存储带小数点的数值。
double:通常为8字节。是双精度浮点数类型,比float类型具有更高的精度和更大的范围。
long double:大小平台相关,但通常是8字节或16字节。是扩展精度的浮点数类型,用于需要更高精度的计算。
其他类型
指针:指针类型的大小也取决于平台和编译器。在32位系统上,指针通常是4字节;在64位系统上,指针通常是8字节。指针用于存储变量的内存地址。
布尔类型(bool):在C99标准之前,C语言没有内置的布尔类型。但自C99起,<stdbool.h>头文件定义了bool、true和false。在大多数实现中,bool类型是通过_Bool关键字实现的,其大小通常为1字节。

那像结构体、类这些自定义类型的大小呢?我们就需要学习内存对齐规则来解决。

内存对齐

以结构体为例,内存对齐规则:

  • 结构体的第一个成员在结构体变量偏移量为0的地址处。
  • 其他成员变量要对齐到某个对齐数的整数倍的地址处。对齐数取编译器默认对齐数(VS默认对齐数是8)与该成员变量类型大小中的较小值。
  • 结构体总的大小是其最大成员对齐值的整数倍。如果结构体中包含嵌套结构体,则嵌套的结构体对齐到自己的最大对齐数的整数倍。
struct ming1
{
	char a;  //1个字节
	int b;   //4个字节
	double c;   //8个字节
};

struct ming2
{
	char a;  //1个字节
	double c;  //8个字节
	int b;   //4个字节
};   

可以看到,存完int 型时20个字节已经足够了,但结构体大小却是24字节,因为要满足规则三(结构体总的大小是其最大成员对齐值的整数倍。)20不是8的整数倍,24是,所以该结构体大小为24字节。

我们可以看到两个结构体中的数据类型是一样的,但类型顺序不同使得两结构体大小不同。

为什么要有内存对齐?

在两个结构体中,如果直接计算三个数据类型之和为1+4+8=13字节,小于16 24字节。很明显内存对齐会浪费空间,但仍采用内存对齐,这与处理器访问字节有关。

  1. 硬件要求:许多处理器和硬件架构对于特定数据类型的访问有严格的对齐要求。例如,某些处理器可能要求访问4字节整数的地址必须是4的倍数,否则可能会导致性能下降甚至错误。这是因为未对齐的访问可能导致额外的处理器周期用于处理数据,从而增加访问时间,降低性能。
  2. 提高访问速度:内存对齐可以使得数据在内存中的布局更加紧凑和连续,减少了因为数据跨越多个内存页或缓存行而导致的额外访问时间。处理器在访问内存时,通常会将数据加载到寄存器或缓存中。当数据对齐时,处理器可以更加高效地从内存中加载数据,而不需要额外的处理步骤,从而提高内存访问的效率。
  3. 平台兼容性:不同的硬件平台可能对于内存访问有不同的要求。内存对齐可以帮助确保代码在各种平台上都能正常运行,提高代码的可移植性和兼容性。

总结

内存对齐用于计算结构体 类的大小,虽然会浪费一些空间,但可以提高访问数据的效率,典型的以空间换取时间。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值