关于内存对齐

内存对齐是操作系统为了快速访问内存而采取的一种策略,简单来说,就是为了防止变量的二次访问。操作系统在访问内存时,每次读取一定的长度(操作系统的默认对齐系数,一般是4或8,或者它的整数倍)。如果没有内存对齐,为了读取一个变量,会产生总线的二次访问!

举个栗子,

struct xx{
        char b;       //0xffbff5e8
        int a;           //0xffbff5e9       
        int c; //0xffbff5ed      
        char d; //0xffbff5f1
};

操作系统先读取0xffbff5e8-0xffbff5ef的内存,再读取0xffbff5f0-0xffbff5f8的内存,这样,因为c的存储空间横跨这2组内存,要得到它的值,就需要将这两组内存合并,进行整合,这样严重降低了内存的访问效率。

这样就能理解为什么结构体的第一个变量,不管类型如何,都是能被8整除的(因为访问内存是从8的整数倍开始的,为了增加读取的效率)!


下面说说各种数据类型的首地址吧,就讲windows上的吧,先。

内存对齐的目的是使各个基本数据类型的首地址为对应K的倍数!

每个基本类型的大小即为这个K,char = 1,int = 4,long = 4,double = 8

举个栗子,

struct test1

{

char a; //0 //1被填充

short b; //2,3

int c; //4,5,6,7

long d; //8,9,10,11 //12-15被填充

double e;//16-23

};

假设从0地址开始,首先a的K值为1,它的首地址可以是任意位置,所以a占用第一个字节,即地址0;然后b的K值为2,它的首地址必须是2的倍数,不能是1,所以地址1的那个字节被填充,b的首地址为地址2,占用地址2,3;然后到c,c的K值为4,它的首地址为4的倍数,所以首地址为4,占用地址4,5,6,7;然后到d,d的K值也为4,所以它的首地址为8,占用地址8,9,10,11.最后到e,它的K值为8,首地址为8的倍数,所以地址12,13,14,15被填充,它的首地址应为16,占用地址16-23.显然其大小为24。


关于结构体里再加结构体的话,得看里面结构体里最大的那个类型,比如

struct test2

{

char f ;

struct test1 g;

}

sizeof(test2) = sizeof(test1)+8;//因为test1结构体里,double最大为8,如果没有double,只有int或long就是+4了

另外,结构体里有enum,就是4,有static 就是0,因为sizeof不统计静态存储。


还有一种特殊的---位段对齐

struct test3
{
unsigned int a:4;
unsigned int b:4;
char c;
};

或者

struct test3
{
unsigned int a:4;
int b:4;
char c;
};

sizeof(test3) = 8;//相邻的多个同类型的数(带符号的与不带符号的,只要基本类型相同,也为相同的数),以上,a和b可作为一个整体,a与b分别位于4字节区域中的前0-3位和4-7位。

struct test4

{

unsigned int a:30;

unsigned int b:4;

char c;

};

sizeof(test4) = 12;//a与b分别分布在第一个4字节的前30位,和第二个4字节的前4位。


struct test5
{
unsigned int a:4;
unsigned char b:4;
char c;
};

sizeof(test5) = 8;//因为int和char不同类型,a和b的值分别位于第一个4字节的前4位,和第5个字节的前4位。

参考网址:http://www.jb51.net/article/44221.htm






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值