关于内存对齐

本文深入解析了内存对齐的概念,解释了为什么CPU偏好对齐的数据,以及如何通过内存对齐提高CPU的内存访问效率。文章通过具体实例展示了不同结构体在内存对齐规则下所占用的实际空间,帮助读者理解内存对齐的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意:该作者博客已迁移至https://buxianshan.xyz

例题:
环境:Win10+VS2017

#include<iostream>
using namespace std;
struct st1{
    char a;
    int b;
    short c;
};
struct st2{
    short c;
    char a;
    int b;
};
int main(){
    cout<<"sizeof(st1) is "<<sizeof(st1)<<endl;
    cout<<"sizeof(st2) is "<<sizeof(st2)<<endl;
    return 0;
}

在不知道内存对齐之前,我会认为sizeof(st1)和sizeof(st2)都是4+1+2=7
但是,输出如下:

sizeof(st1) is 12
sizeof(st2) is 8

什么是内存对齐?

在程序员眼中内存是由一个个字节组成的。
在这里插入图片描述
但是CPU不这么看。CPU把内存当成是一块一块的,块的大小可以是2,4,8,16 个字节,因此CPU在读取内存的时候是一块一块进行读取的,块的大小称为(memory granularity)内存读取粒度。因此CPU在读取内存时是一块一块进行读取的。
在这里插入图片描述

为什么要内存对齐?

看个例子:
假设内存读取粒度(即块大小)为4。CPU要读取一个int型4字节大小的数据到寄存器中,简单分两种情况讨论:

  1. int数据在0,1,2,3字节
  2. int数据在1,2,3,4字节

在这里插入图片描述
第一种情况,从0字节开始读,CPU很顺利地读到了一个int数据。但是第二种情况,CPU先访问一次内存,读取0—3字节的数据进寄存器, 并再次读取4—7字节的数据进寄存器,接着把 0 字节和 5 , 6,7字节的数据剔除,合并1,2,3,4字节的数据进寄存器,这才能成功读取该int型数据。
对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。经过内存对齐之后,CPU的内存访问速度大大提升。

内存对齐的规则:

  1. 对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是这个数据成员的自身长度 的倍数。
  2. 在数据成员完成各自对齐之后,结构体本身也要进行对齐,对齐将按结构体最大数据成员长度进行。

例题分析:

St1 :char +int+short
st1结构中最大数据成员长度为int,占4字节。所以结果本身按照4字节对齐,结构总大小必须为4的倍数
char占1个字节,起始偏移为0 。
int 占4个字节,所以int按4字节对齐,起始偏移必须为4的倍数,所以起始偏移为4,在char后编译器会添加3个字节的额外字节。
short占2个字节,按2字节对齐,起始偏移为8,正好是2的倍数,无须添加额外字节。但是需添加2个额外字节使结构的总大小为12 (4的倍数)。
到此内存对齐结束。St1占用了12个字节而非7个字节。oxxx|oooo|ooxx (x代表额外的字节)
同理St2:short + char + int 占用8个字节。oo|ox|oooo 。

感谢

  • 李昕老师(CUMT)
  • https://www.cnblogs.com/jijiji/p/4854581.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值