字节对齐

1.为什么要字节对齐

内存按byte(字节)划分,而数据类型最小的也就一个字节,所以理论可以从任何地址开始访问,但实际访问特定

类型变量的时候经常在特定的内存地址访问。不同数据类型按一定规则在空间排列,而不是顺序排列,这就需要字节对齐。

2.几个术语

自身对齐值:数据类型自身的大小(sizeof)

指定对齐值:编译器指定按几个字节进行对齐

有效对齐值:自身对齐值和指定对齐值较小的那一个(最终用来决定数据存放地址的值)

有效对齐值为4,则表示数据存放占4字节,起始字节的地址%4=0,满足这个条件

结构体,类的自身对齐值为数据成员中自身对齐值最大的那一个值

3.例子

所谓对齐,指的是变量存储时候以有效对齐值确定起始地址

如一个结构体,地址从0x0000 0000开始(32位系统,寻址2的32次方=4G)

struct B{

char a;   //1字节

int b;   //4字节

short c;}   //2字节

编译器默认指定对齐值为4字节(#pragma pack(8) //指定8字节对齐    //code    #pragma pack()//恢复默认)

char a---自身对齐值:1;指定对齐值:4;有效对齐值:1;地址:0x0000 0000%1=0 所以地址为0x0000 0000

int b---自身对齐值:4;指定对齐值:4;有效对齐值:4;地址:0x0000 0001%4=1 所以地址为0x0000 0004

short c---自身对齐值:2;指定对齐值4;有效对齐值:2;地址:0x0000 0008%2=0 所以地址为0x0000 0008

总的内存地址为0x0000 0000-0x0000 00009   |char| | | |int | | | |short| |=10字节


64位机器:一个指针占8字节,Linux下默认8字节字节对齐

32为机器:一个指针占4字节,Linux下默认4字节字节对齐

T* d_sto;//指针,占8字节

#define SIZE ((long)d_sto&7L)

因为字节对齐是8字节,所以d_sto的地址只能是0x0000 0000 0000 1000

                                                                                   0x0000 0000 0001 0000

也就是8的倍数,因此地址存储空间中的后三位都是0,所以SIZE就把后三位拿来用了。(之前没考虑到这个是因为

没有考虑到指针也是有存储空间的,没注意到指针存储时候的字节对齐)

指针与7之后这个指针表示的地址就是无效的,所以在访问该指针地址的内容时候,还要还原

#define STORE ((T)(long)d_sto&~7L)

这样就变回了有效的指针。


#define SIZE2 (SIZE/(sizeof(T)>>2)

有一个T时候,SIZE=1,sizeof(T)=4,sizeof(T)>>2=1, SIZE2=1

有一个T时候,SIZE=1,sizeof(T)=8,sizeof(T)>>=2,SIZE2=2

也就是说如果T是int的话,一个T就代表存了一个int

如果T的类型比如是long的话,则一个T就用两个int的空间来存储,也就是说代表存了2个int

sizeof(T)>>2表示的是以4字节为模块分组


再来一个总结:(64位指针为8字节,16进制是按bit来的,4位代表两个字节)

#define size ((long)d_sto&7L) 

#define store ((T)(long)d_sto&~7L)

这两个宏定义把一个地址分成了两部分0x0000 0000 0000 000(0-000)即6*8+1*8+4+1=61表示地址,最后3bit表示数据。因为内存是按8字节对齐的,所以后三位一直是0,故用来存数据size。

int32* news=(int32*)malloc(newsize);

d_sto=(T*)((long)news+newsize);

这里news表示地址,(long)news表示的就是一个值(把指针地址转化成了长整形),故(long)news+newsize就相当于

把newsize存入到了后三位中,前提是newsize的值不能大于7(保证3bit存的下)



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值