C/C++字节对齐分析

今天突然用到了字节对齐的知识,所以看了几遍文章并做了些测试,总结如下

参考:

1.http://user.qzone.qq.com/279764633?ADUIN=1522421539&ADSESSION=1428455121&ADTAG=CLIENT.QQ.5389_FriendInfo_PersonalInfo.0&ADPUBNO=26441&ptlang=2052

2.http://blog.csdn.net/kokodudu/article/details/11918219

3.http://www.cnblogs.com/repository/archive/2011/01/13/1933721.html

一.先看以下代码:

#include <iostream>
using namespace std;

struct A
{
    int a;
    char b;
    short c;
};

struct B
{
    char a;
    int b;
    short c;
};

#pragma pack(2)
struct C
{
    char a;
    int b;
    short c;
};

#pragma pack(1)
struct D
{
    int a;
    char b;
    short c;
};

int main()
{
    cout << sizeof(A) << "   "<< sizeof(B)<< "   "<< sizeof(C)<< "   "<< sizeof(D)<<endl;
    return 0;
}
输出结果为

8 12 8 7

理论上来说,结构体A与B的大小应该都是一样的,造成这种原因的就是字节对齐引起来的

二.为什么要对齐呢?

简单点说:为了提高存取效率。字节是内存空间分配的最小单位, 在程序中,我们定义的变量可以放在任何位置。其实不同架构的CPU在访问特定类型变量时是有规律的,比如有的CPU访问int型变量时,会从偶数地址开始读取的,int类型占用4个字节(windows平台)。 0X0000,0X0004,0X0008.....这样只需要读一次就可以读出Int类型变量的值。相反地,则需要读取二次,再把高低字节相拼才能得到 int类型的值,这样子看的话,存取效率当然提高了。

三.编译器对字节对齐的一些规则

1.基本类型的自身对齐值:

类型对齐值

char    1

short   2

int       4

float    4

double 4(double自身长度虽然在x64上是8,但是它的对齐长度还是4

2.类和结构体的对齐字节值:使用成员当中最大的对齐字节来对齐。比如在Struct A中,int a的对齐字节为4比char,short都大,所以A的对齐字节为4。

3.指定对齐值:使用了宏 #pragma pack(n)来指定的对齐值

4.类、结构及成员的有效对齐字节值:有效对齐值=min(类/结构体/成员的自身对齐字节值,指定对齐字节值)。有效对齐其实就是要求数据成员存放的地址值能被有效对齐值整除,即:地址值%有效对齐值=0如果没有指定对齐字节值就使用编译器默认字节对齐值,这个值一般都大于4(为4或者8,64位g++多数网友说是8位),所以一般不会影响判断

规则虽然很多,但是我们实际使用中很少用到自己指定对齐值,所以后面3,4规则很少起作用,判断结构体占用字节或者sizeof返回值时主要根据1,2规则

四.实例分析

从刚开始给的例子的A和B可以看出,内存对齐与结构体中变量声明的顺序有关

struct A
{
    int a;
    char b;
    short c;
};
step 1: 根据第二条,首先为结构体选择对齐值:选择成员中最大的对齐值,即int a,对齐值为4

step 2: 再根据第四条原则,决定有效对齐值为4

step 3: int a 的有效地址值为4,这样a的地址就是从 0X0000~0x0003 

step 4: char b 的有效对齐值为1,地址依次从0x0003 (因为Ox0003%1=0)开始,分配一个字节,char b地址段分配情况就是:0x0003~0x0004

step 5: short c 的有效对齐值为2,理论上说,分配的地址应该是连续的(从0x0005~0x00006),但是由于要求考虑到对齐的情况,所求要求地址段偏移,这样就从0x0006(Offset+1,因为0x0006%2=0)开始,分配2个字节的地址0x0006~0x0007.

目前为止,地址段的分配情况就是:0x0000~0x0007这样sizeof(A)的大小=0x0000~0x0007共8个字节大小,同时,8%4=0保证了Struct A的地址段与4成偶数倍。

struct B
{
    char a;
    int b;
    short c;
};
step 1: 确实结构体B对齐值:选择成员中最大的对齐值,即int a,对齐值为4

step 2: char a 的有效地址值1,a的地址就是 0X0000(因为0x0000%1=0)

step 3: int b 的有效对齐值4,地址依次从0x0004~0x0007 (因为Ox0004%4=0)开始,分配4个字节,目前j地址段分配情况就是:0x0000~0x0007

step 5: short c 的有效对齐值2,c从0x0008~0x0009(因为0x0008%2=0)开始.

至止,地址段的分配情况就是:0x0000~0x0009共10个字节,但是Struct B的对齐值为4,这就要求地址地段再偏移2个字节,这样就是从0x0000~0x000B共12(因为12%4=0)个字节大小。这样,sizeof(B)=12

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值