内存对齐

1.CPU如何读取内存

  CPU在处理内存的过程中,是把内存当做一块一块来处理的,每一块可以是2,4,8或16bytes。假设CPU读取块的大小是4bytes
  其中一块内存分布如图:
  这里写图片描述
  假设我们读取第一个char类型,那么CPU会读取0-3地址的4bytes的内存,存入寄存器,然后踢出1-3部分的内存,最后得到char类型的变量值。然后读取int类型,此时CPU是不能直接读取1-4地址空间的,只能读取0-3地址内存,通过移位提出0位置地址,并空出一个byte的空间,然后读取4-7地址的内存,通过移位,踢出5-7地址的内存,只剩4位置的内存值,然后剩余的1-3地址和4地址进行组合,构成此时的int值。这样的操作效率很低。当然,如果硬件系统并不支持这种“合并”的操作,那么读取内存操作就会崩溃。
  试想,假如我们就把char存在0-3地址空间空间,int存储在4-7地址空间那么CPU就可以直接读取两个变量的值,虽然耗费了空间,但是CPU读取内存的效率确实大大增加了。事实上,操作系统在分配内存的时候就是按照这种方式进行的,也就是内存对齐。

2.内存对齐原则

规则:

  • 类内数据成员先自身对齐(地址值%自身所占空间长度 == 0)
  • 类整体在进行对齐(内存尾地址值%min(#pragma pack, 类中数据成员最长长度) == 0)

下图是一张内存中的部分地址图:
 这里写图片描述
 
我们定义类

struct A{
    char a;
    int b;
}
  • 首先存储char类型变量,那么数据成员自身对齐就是:
          偏移地址%自身所占内存长度 == 0
    所以a存在0x00位置。
  • 存储int类型,按照由低到高的顺序访问地址,发现第一个满足对齐的地址是0x04,那么b变量就从这个位置开始存储。
  • 存储完成后,整体在对齐。此时的内存空间是这样的:
    这里写图片描述
    sizeof(A);//8

在次定义结构体

struct B{
    int a;
    char b;
    short c;
}

分配规则相同,那么此时的内存分布图:
这里写图片描述
sizeof(B);//8
那么同理,sizeof(C);//12

struct C {
    char a;
    int b;
    short c;
}

3.预处理器语法

前文中提到#pragma pack()这是预处理器自定义的对齐参数,默认是8。
- #pragma pack(show)可以查看默认对齐参数,在编译器中以warning形式给出
- 通过以下代码可以自定义内存对齐的数值

#pragma pack(push)
#pragma pack(n)
...//这里是n对齐
#pragma pack(pop)
...//这里是默认对齐

n的取值可以是1,2,4,8,16。

4.32位和64位编译器各类型所占空间

注意int和long类型。

32位编译器:
      char1个字节
      char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
      short int : 2个字节
      int4个字节
      unsigned int : 4个字节
      float:  4个字节
      double:   8个字节
      long:   4个字节
      long long:  8个字节
      unsigned long:  4个字节
64位编译器:
      char1个字节
      char*(即指针变量): 8个字节
      short int : 2个字节
      int4个字节
      unsigned int : 4个字节
      float:  4个字节
      double:   8个字节
      long:   8个字节
      long long:  8个字节
      unsigned long:  8个字节
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值