内存对齐问题的一些总结

要了解为什么要内存对齐,首先我们要了解什么是内存对齐

什么是内存对齐 
关于什么是内存对齐,我们先来看几个例子

typedef struct {
    int a;
    double b;
    short c;
}A;
typedef struct {
    int a;
    short b;
    double c;
}B;

分别对他们求大小,sizeof(A),sizeof(B)我们所得到的结果是不同的, 
sizeof(A)=24而sizeof(B)=16为什么会产生不一样的结果呢? 
这是非常简单的一个例子,体现了结构体的内存对齐规则。 
在结构体中,从结构体的首地址开始,假设地址从0开始。 
对结构体A来说,a占4个字节,占从0~3的字节,b是double类型占8个字节,占从8~15的字节,c占两个字节,从16~17的字节。 
对结构体B来说,a占4个字节,从0~3,b占两个字节从4~6;c占8个字节从8~15。 
这就是内存对齐,对齐规则是按照成员的声明顺序,依次安排内存,其偏移量为成员大小的整数倍,0看做任何成员的整数倍,最后结构体的大小为最大成员的整数倍(所以这里的A的大小是24,而不是18)。

C语言和C++中空类和空结构体的大小 
在C++中规定了空结构体和空类的内存所占大小为1字节,因为c++中规定,任何不同的对象不能拥有相同的内存地址(编译器自动增加空类和空结构体一个指针来进行区分)。 
而在C语言中,空的结构体在内存中所占大小为0。(gcc中测试为0,其他编译器不一定)

为什么要内存对齐? 
1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 
2.性能原因(硬件原因):cpu把内存当成是一块一块的,块的大小可以是2,4,8,16 个字节,因此CPU在读取内存的时候是一块一块进行读取的,块的大小称为(memory granularity)内存读取粒度。

我们再来看看为什么内存不对齐会影响读取速度?

    假设CPU要读取一个4字节大小的数据到寄存器中(假设内存读取粒度是4),分两种情况讨论:

           1.数据从0字节开始

        2.数据从1字节开始

解析:当数据从0字节开始的时候,直接将0-3四个字节完全读取到寄存器,结算完成了。

        当数据从1字节开始的时候,问题很复杂,首先先将前4个字节读到寄存器,并再次读取4-7字节的数据进寄存器,接着把0字节,4,6,7字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器,对一个内存未对齐的寄存器进行了这么多额外操作,大大降低了CPU的性能。

     但是这还属于乐观情况,上文提到内存对齐的作用之一是平台的移植原因,因为只有部分CPU肯干,其他部分CPU遇到未对齐边界就直接罢工了。

转自: 为什么要进行内存对齐以及对齐规则

           什么是内存对齐?为什么要内存对齐?

猜你喜欢

转载自blog.csdn.net/weixin_43871369/article/details/91441956