概述
看了几遍 sizeof 的内容,老是忘记,这里做下笔记,以供复习与参考。
sizeof(a)用来计算a所占字节大小,其中a可以是类型名,也可以是变量,亦或是对象、函数。
1) sizeof (int); //类型
2) sizeof (a); //int a;变量
3) sizeof (a); //class A; A a;对象
4) sizeof(function_name);//计算的是函数返回类型的值
在计算结构体大小时,由于字节对齐的缘故,需要考虑3个准则(后面有示例):
1.计算前,注意首地址——保证结构体的首地址能被最宽的基本类型成员大小所整除(除非给定了首地址,否则默认首地址为0)。
2.计算时,注意成员偏移量——保证每个成员相对首地址的偏移量是该成员大小的整数倍(注意这里的成员是指此时正在计算的成员,而不是最宽基本类型成员)。
3.计算后,注意总体大小——结构体的总大小应该是结构体中最宽基本类型成员大小的整数倍。
另外,需要注意以下3个问题:
1.上述中说的是都是基本类型,即char(1),short(2),float(4),int(4),double(8),对于结构体嵌套的情况,比如:
struct S{
char a;
float b;
int c;
double d;
};//S结构体大小为24
struct B{
int a;
S b;
char c;
};
其中结构体B中嵌套了S,而且S的大小比其他基本类型的大小都大,但我们在计算B的大小时只能按照最宽的基本类型计算(这里是double),而不是按照S的大小作为最宽大小。
2.对于某一类型的指针,其自加或自减所得到的新地址为:A.新地址=A.旧地址+sizeof(A)*step。
比如 struct S s;假设s初始地址为0,自加后的新地址为:0+24*1=24。
3.结构体中,如果定义顺序不同,会影响结构体的总体大小,如:——这里是计算示例
struct S1
{
short a;//2
int b;//4
short c;//2
};
//我们按照上面说的三步走
//1.计算前,首地址为最大基本类型的整数倍,一般默认从0开始,0整除4,没毛病。
//2.计算中:保证每个成员相对首地址的偏移量是该成员大小的整数倍:
//计算a时,由于0可以整除2,故a从0开始,占2个字节-[0,2)
//计算b时,参考准则2,由于2不能整除4,需要在a的后面补2个字节,然后b从4开始,占4个字节-[4,8)
//计算c时,由于8可以整除2,因此不需要补齐字节,所以c从8开始,占2个字节-[8,10)
//3.计算后,上述算的的总体大小为10,根据准则3,总体大小应为最大基本类型(这里是int)的整数倍,因此这里需要补2个字节,所以,最后总体大小为12.
struct s2{
short a;
short c;
int b;
}//通过上述方法可算得,s2的大小为8
所以我们在计算结构体大小时,应按照定义顺序计算。
4.变长结构体不能使用sizeof计算
另外需要注意的是sizeof是关键字,不是函数,它是在编译时计算的,所以他只会算实际分配的内存大小,而不管你用了多少(用了多少是你运行之后确定的),也因此它不能计算动态分配的内存大小。反观strlen,他是一个函数,用来计算字符串的长度,遇到‘ ’结束。函数是在运行时起作用的,所以他计算的是实际有多少内存(以’ ’为界)。
另外,可以通过
#pargma push pack(n)
来设置对齐规则
最后
以上就是清新萝莉为你收集整理的sizeof计算大小规则(一看就会)的全部内容,希望文章能够帮你解决sizeof计算大小规则(一看就会)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复