字节对齐和sizeof函数的计算方法

作者: 红色黎明 分类: C++,学习笔记 发布时间: 2012-10-13 00:02

最近参加的笔试中挺多考到了字节对齐和sizeof() 函数,特别是多益网络的笔试,整张试卷很多都是关于内存地址计算的题目。所以今天特别参考了同学(koppt)的博客和其他的一些资料,顺便把这两个技术类岗位笔试时最常见的问题的计算方法总结了出来。

1、sizeof() 函数

sizeof() 函数可以计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示(当然用在字符数组计算”\0″的大小)。

1)计算指针。指针均可看为变量类型的一种。所有指针变量的sizeof() 操作结果均为4。

char *p;

sizeof(p)=4;        //相当于计算p指针的大小

sizeof(*p) = 1;    //相当于sizeof(char)

2)对于静态数组,sizeof() 可直接计算数组大小。

int a[10];                    //int类型为4个字节,所以sizeof(a)等于4*10=40。

char b[]=”hello”;     //sizeof(b)等于6,由于”hello”字符串最后默认会有”\0″,所以多了一个字节。

char p[];                     //sizeof(p);  数组名称当作指针使用,所以其实此处计算的是指针的大小,为4。

3)二维或以上维度的数组

double* (*a)[3][6];         //a表示一个指向double* [3][6]类型数组的指针。注意此处数组中的各个元素也是指针。

sizeof(a)                             //数组名a当作指针,所以大小为4

sizeof(*a)                           //*a为一个有3*6个指针元素的数组,所以大小为4*3*6=72

sizeof(**a)                         //**a为第一个一维数组的6个指针,所以大小为4*6=24

sizeof(***a)                       //***a为第一个一维数组的第一个指针,所以大小仍为指针的大小4

sizeof(****a)                     //****a为一个指向double类型的变量,所以大小为8

2、字节对齐

字节对齐的作用和原因:

各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐,其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据,显然在读取效率上下降很多。

内存对齐的规则:

1)  对于结构的各个成员,第一个成员位于地址偏移为0的位置,以后每个数据成员的地址偏移值必须是min (#pragma pack()指定的数,这个数据成员的自身长度)的倍数。

2)  在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照min(#pragma pack()指定的数值,结构或联合最大数据成员长度)的值进行。即结构(或联合)的字节空间大小为前面说的min值的倍数。

#pragma pack(n) 表示设置为n字节对齐,这里VC默认8字节对齐。(可以查看VC的默认设置)

示例:

1)结构的字节对齐

struct s1

{

char a;

double b;

int c;

char d;

};

思路:

1、先考虑struct中各个数据成员的对齐。对于s1,首先假定初始地址是0,把a放在0,char型占用1个字节,此时下一个空闲的地址是1,但是下一个元素b是double类型(8个字节),要放到8的倍数的对界上,离1最接近的地址是8,所以b被放在了8,此时下一个空闲地址变成了16,下一个元素c占用4个字节,而此时地址为16(是4的倍数)可以满足,所以c放在16上,此时下一个空闲地址变成了20,下一个元素d占用1个字节,20为1的倍数满足条件,所以d放在了20,结构体在地址20处结束,共占用21个字节。

2、再考虑struct整个结构的对齐。由于s1的大小需要是8的倍数,所以地址为21-23的空间被保留,s1的大小变成了24。

2)结构体中包含有结构的成员,需要实际考虑

struct s1                    //按上述对齐规则可得sizeof(s1)的大小为1*8=8,以1个字节对齐

{

char a[8];

};

struct s2                  //按上述对齐规则可得sizeof(s2)的大小为8,以8个字节对齐
{

double d;

};

struct s3                 //因为s1的整体结构是以1个字节对齐,所以此时s3的整体结构也是以1个字节对齐,即sizeof(s3)=8+1=9,为1的倍数符合

{

s1 s;

char a;

};

struct s4                 //因为s2的整体结构是以8个字节对齐,所以此时s4的整体结构也是以8个字节对齐,即sizeof(s3)=8+1+7=16为8的倍数符合

{

s2 s;

char a;

};

参考资料出处:  http://kopptblog.sinaapp.com/2012/04/19/dataalignment/

http://blog.sina.com.cn/s/blog_5c717fa001012ml7.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注