内存字节对齐、为什么要对齐

内容会持续更新,有错误的地方欢迎指正,谢谢!

内存字节对齐

对齐的三个原则

如何内存对齐?sizeof的结果怎么来的?请记住以下3条原则:(在没有#pragma pack宏的情况下)

  1. 原则1:结构(struct)或联合(union)的数据成员,存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如:假设一个数据成员为int,int在32位机上为4字节,则要从4的整数倍地址开始存储)
  2. 原则2:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(比如:struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储)
  3. 原则3:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

内存字节对齐的原因

根本原因在于CPU访问数据的效率问题。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。显然在读取效率上下降很多。

举例1

typedef struct bb
{
    int id;            //0~3
    double weight;     //8~15   原则1
    float height;      //16~19  要为8的整数倍,补齐20~23  原则3
}BB;

typedef struct aa
{
 char name[2];     //0~1   申请了两个char空间,所以是占用2个字节
 int  id;          //4~7   原则1
 double score;     //8~15
 short grade;      //16~17    
 BB b;             //24~47   要从8的整数倍开始存  原则2
}AA;

int main()
{
  AA a;
  cout<<sizeof(a)<<" "<<sizeof(BB)<<endl;
  return 0;
}

结果是48 24

举例2

在32位cpu上选择缺省对齐的情况下,有如下结构体定义:

struct A
{
    unsigned a : 19;//后面的数字表示bit
    unsigned b : 11;
    unsigned c : 4;
    unsigned d : 29;
    char index;//1个字节=8bit
};

则sizeof(struct A)的值为?

解答:由32位缺省对齐,所以有:
由于19+11=30<32,19和11算作32位,即4个字节
由于4+29>32,4算作32位,即4个字节
由于29+8>32,29算作32位,即4个字节
由于8<32,8算作32位,即4个字节

所以,总共有16个字节!sizeof(struct A)的值为16。

用pragma控制内存对齐

再讲讲#pragma pack():在代码前加一句#pragma pack(1),你会发现上面的代码输出为32 16,因为bb是4+8+4=16,aa是2+4+8+2+16=32。这不就是理想中的没有内存对齐的世界嘛。

下面的代码,在#pragma pack(4)#pragma pack(8)的情况下,结构体的大小分别是:

struct One{  
    double d;  
    char c;  
    int i;  
}  
struct Two{  
    char c;  
    double d;  
    int i;  
}  

这里写图片描述

所以,答案为16,16,16,24

猜你喜欢

转载自blog.csdn.net/billcyj/article/details/79936359