linuxc/c++内存对齐

为什么要内存对齐?

尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存。

现在考虑4字节存取粒度的处理器取int类型变量(32位系统),该处理器只能从地址为4的倍数的内存开始读取数据。假如没有内存对齐机制,数据可以任意存放,现在一个int变量存放在从地址1开始的联系四个字节地址中,该处理器去取数据时,要先从0地址开始读取第一个4字节块,剔除不想要的字节(0地址),然后从地址4开始读取下一个4字节块,同样剔除不要的数据(5,6,7地址),最后留下的两块数据合并放入寄存器。为了访问未对齐的内存,处理器可能需要作两次内存访问;而对齐的内存访问可能仅需要一次访问。总的来说,结构体的内存对齐是拿空间来换取时间的做法。

内存对齐规则
  • 每个变量相对于起始位置的偏移量必须是该变量类型大小的整数倍,不是整数倍空出内存,直到偏移量是整数倍为止;
  • 如果设置了内存对齐(对齐参数)为 i 字节,结构体中最长数据类型长度为j,那么整体有效对齐值n = min(i, j) ;
  • 每个成员对齐规则:类中第一个数据成员放在offset为0的位置;对于其他的数据成员(假设该数据成员字节数为k),放置的起始位置offset应该是 min(k, n) 的整数倍;
  • 最后整个结构体或类的大小应该是n的整数倍。
对齐参数

windows中,VS编译器下,默认对齐数为8; Linux中,默认对齐数为4 ;
设置对齐参数可在结构体struct之前加上预编译命令#pragma pack(对齐数),在struct之后加上#pragma pack;便可以设置对齐参数。
对齐参数不能任意设置,只能是内置类型已有的字节数,如:char(1)、short(2),int(4),double(8)…,不能是3,5…任意数

#pragma pack(4)
struct   A
{
    int a;
    char b;
    double c;
    char d;
};
#pragma pack();

实例分析

#include<iostream>
using namespace std;
#pragma pack(2) // 设置对齐参数2,整体n = min(2, sizeof(int))) = 2
struct   A
{
    char c; //放在位置0,位置区间[0]
    int i; //4 > n, 那么放置起始位置应该是2的倍数,即2,位置区间为[2~5]
    short s; //2 = n,那么放置起始位置应该是2的倍数,即6,位置区间为[6~7]
};
#pragma pack() // //取消设置的默认对齐数,还原为默认

int  main()
{
    struct A a;
    cout << sizeof(a); // 8
    return 0;
}

参考:https://zhuanlan.zhihu.com/p/30007037

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值