关于c++中内存对齐的一些问题

假设有以下代码:

#include <stdlib.h>
#include <stdio.h>

class A{
    int a;
    short b;
    char c;
    int d;
};

class B{
    double e;
    int f;
    short g;
    char h;
    
};

int main(){
    printf("%4d, %4d\n", sizeof(A), sizeof(B));
    return 0;
}

源码文件为Test.cpp,在64位机器上编译运行
#g++ Test.cpp -o Test

#./Test

int是4个字节,short2个字节,char1个字节,理论上A因该是4*2+2+1=11个字节啊,为啥是12呢,实际上可以这样理解,

内存是4个字节一块,对于class A, a占4个,b和c占4个字节,d占4个字节,一共12个字节,b和c占的那4个字节中虽然有一个字节没有利用,但是也不能存下d,需要额外再搞4个字节。

对于class B, double在64位机器上是8个字节,所以是e8个字节,f4个字节,g和h4个字节,一共16个字节。

有趣的是如果我们调整一下A和B中变量的顺序,得出的结果也不一样,所以上述思路还有问题。

例如

class A{
    int a;
    short b;
    int d;
    char c;
};

class B{
    double e;
    short g;
    int f;
    char h;
};

那么输出结果又变了

实际上,仔细想想,还是那个道理,就是内存中4个字节是一块,对于class A,a占4个字节,b占四个字节,d占4个字节,c占4个字节,虽然浪费了5个字节,但是前一个变量没有利用的字节,也不能放下后一个变量。

按照这个理论,class B应该是占20个字节啊,怎么又是24呢,我们可以这么想,既要4字节对齐,又要8字节,e占8个字节,g和f占8个字节,h占8个字节,一共24个字节。而上面的class B是e8个字节,f,g,h占8个字节,一共16个字节。

我们还可以修改一下程序,进一步验证猜想,例如:

class A{
    char a;
    short b;
    int c;
    int d;
};

class B{
    char e;
    short f;
    int g;
    double h;
};

我们按照从小到大去排列变量,那么结果又是怎样呢。

class A是:a和b占4个字节,c,d各4个字节,一共12;class B e,f,g占8个字节,h8个字节,一共16。由此可见,我们可以得到两个明显的规律;

1.如果变量的大小不超过int,那么就是4字节对齐。(有待验证)

2.如果有double long, 那么就需要8个字节对齐。

对于1,我们修改一下程序:

class A{
    char a;
    short b;
    //int c;
    //int d;
};

class B{
    char e;
    //short f;
    //int g;
    //double h;
};

那么结果是这样的

实际上,如果类中只用一个char变量,那么它的大小只有1,而不是4。

对程序再次修改

class A{
    short a;
    short b;
    //int c;
    //int d;
};

class B{
    char e;
    char f;
    //short f;
    //int g;
    //double h;
};

那么结果又是怎样呢。

再次修改程序

class A{
    short a;
    short b;
    short c;
    //int c;
    //int d;
};

class B{
    char e;
    char f;
    char g;
    //short f;
    //int g;
    //double h;
};

结果是这样的:

由此可见,在分配内存的时候,是以类中最长的那个变量类型作为对齐标准的,而不是int,可以是1(char),2(short), 4(int), 8(long, double),此外,如果结构体中即有double又有int,那么还要考虑4字节对齐,比如

class B{
    double e;
    short g;
    int f;
    char h;
};

占用的是24字节,而不是16字节,尽管8个字节可以存下g,f,h. 

测试用的平台是Ubuntu12.01键入uname --m输出x86_64,操作系统是 64位,gcc版本是4.7。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值