sizeof详细解读

//By Richard
#include <stdio.h>
#include <string.h>

char foo()
{
	printf("foo() has benn called.\n");
	return 'a';
}
int foo1()
{
	printf("foo1() has benn called.\n");
	return 0;
}
int foo2(char a2[2])
{
	int a=sizeof(a2);
	return a;
}
int foo3(char a3[])
{
	int a=sizeof(a3);
	return a;
}
struct S1
{
	char c;
	int i;
};
struct S2
{
	int i;
	char c;
};
struct S3 
{ 
	 char c1; 
	 S1 s; 
	 char c2; 
};
union U
{
	int i;
	char c;
	S1 s;
};

int main()
{
	//一、基本数据类型
	printf("sizeof(int) is : %d\n",sizeof(int));//4
	printf("sizeof(unsigned int) is	: %d\n",sizeof(unsigned int));//4
	printf("sizeof(short) is : %d\n",sizeof(short));//2
	printf("sizeof(unsigned short) is : %d\n",sizeof(unsigned short));//2
	printf("sizeof(long) is	: %d\n",sizeof(long));//4
	printf("sizeof(unsigned long) is : %d\n",sizeof(unsigned long));//4
	printf("----------------------------\n");
	printf("sizeof(char) is	: %d\n",sizeof(char));//1
	printf("sizeof(unsigned char) is : %d\n",sizeof(unsigned char));//1
	printf("----------------------------\n");
	printf("sizeof(float) is : %d\n",sizeof(float));//4
	printf("sizeof(double) is : %d\n",sizeof(double));//8
	printf("sizeof(long double) is : %d\n",sizeof(long double));//8
	printf("----------------------------\n");

	//typedef unsigned int size_t;
	printf("sizeof(size_t) is: %d\n",sizeof(size_t));//4
	printf("----------------------------\n");
	
	printf("sizeof(2) is: %d\n",sizeof(2));//4
	printf("sizeof(2+3.14) is: %d\n",sizeof(2+3.14));//8
	printf("----------------------------\n");

	//二、sizeof可以对一个函数调用求值,其结果是函数返回类型的大小
	//函数并不会被调用
	printf("sizeof(foo()) (return 'a') is: %d\n",sizeof(foo()));//1
	printf("sizeof(foo1()) (return 0) is: %d\n",sizeof(foo1()));//4
	printf("----------------------------\n");

	//三、sizeof的常量性
	//sizeof的计算发生在编译时刻,所以可以被当做常量表达式使用
	//比如说,定义数组 char ary[sizeof(int)*10];

	//四、指针变量的sizeof
	//在32位计算机中,一个指针变量的返回值必定是4(个字节)
	//原因:指针记录了另一个对象的地址,等于计算机内部地址总线的长度
	//64位系统中指针变量的sizeof结果为8

	//测试指针所用变量
	char *pc="abc";
	int *pi;
	//string *ps;
	char **ppc=&pc;
	void (*pf)();//函数指针

	printf("sizeof(pc) is: %d\n",sizeof(pc));//4
	printf("sizeof(pi) is: %d\n",sizeof(pi));//4
	//printf("sizeof(ps) is: %d\n",sizeof(ps));//4
	printf("sizeof(ppc) is: %d\n",sizeof(ppc));//4
	printf("sizeof(pf) is: %d\n",sizeof(pf));//4
	printf("----------------------------\n");

	//五、数组的sizeof
	char a1[]="abc";
	int a2[3];
	printf("sizeof(a1) is: %d\n",sizeof(a1));//4,原因:a1有4个字符(包括'\0'),每个字符占一个字节
	printf("sizeof(a2) is: %d\n",sizeof(a2));//12,原因:a2有3个int型数字,每个int型站4个字节
	printf("----------------------------\n");

	//求数组元素的个数
	int c1=sizeof(a1)/sizeof(char);
	int c2=sizeof(a2)/sizeof(int);
	printf("c1 is: %d\n",c1);//4
	printf("c2 is: %d\n",c2);//3
	printf("----------------------------\n");

	//六
	/*函数在上面已经定义,写在这里只是为了看起来方便
	int foo2(char a2[2])
	{
		int a=sizeof(a2);
		return a;
	}
	int foo3(char a3[])
	{
		int a=sizeof(a3);
		return a;
	}
	*/
	char aa2[2];
	char aa3[]="hello";
	printf("The value of foo2() is : %d\n",foo2(aa2));//4
	printf("The value of foo3() is : %d\n",foo3(aa3));//4
	printf("----------------------------\n");
	//为什么都是4哦?
	//这里函数参数aa2、aa3已不再是数组类型,而是蜕变成指针,相当于char *aa2
	//我们调用函数foo2时,程序会在栈上分配一个大小为3的数组吗?不会!数组是“传址”的,
	//调用者只需将实参的地址传递过去即可,所以aa2和aa3自然为指针类型(char*),a的值也就为4
	//即一个指针所占的字节数,为4

	//七、结构体的sizeof	
	/*
	struct S1
	{
		char c;
		int i;
	};
	struct S2
	{
		int i;
		char c;
	};
	struct S3 
	{ 
	char c1; 
	S1 s; 
	char c2; 
	};
	*/
	S1 s1={'A',1};
	S2 s2={1,'A'};
	S3 s3={'A',s1,'B'};
	printf("sizeof(s1) is :%d\n",sizeof(s1));//8
	printf("sizeof(s2) is :%d\n",sizeof(s2));//8
	printf("sizeof(s3) is :%d\n",sizeof(s3));//16
	printf("----------------------------\n");
	/*************************************************************************
	*1,字节对齐的细节和编译器实现相关,但一般而言,满足三个准则: 
	*(1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除; 
	*(2)结构体每个成员相对于结构体首地址的【偏移量】(offset)都是成员大小的整数倍,
	*	如有需要编译器会在成员之间加上填充字节(internal padding); 
	*(3)结构体的【总大小】为结构体最宽基本类型成员大小的整数倍,
	*	如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
	*****(3个我们判断的依据,第一个准则可以不用考虑,因为编译器已经实现了)*****
	*2,调试程序,查看s1和s2的内存分布
	*	s1:41 cc cc cc 01 00 00 00
	*	s2:01 00 00 00 41 cc cc cc
	*	cc为填充字符,16进制的41为65,即为'A',01表示1
	*	s1中,int型占4个字节,偏移量得从4开始,所以前面得填充字节
	*	s2中,总大小不可能为5个字节,只能为4的倍数,为8,后面得填充字节
	*	(成员大小指char定义的成员或int定义的成员)
	*3,分析S3(复合型)
	*	s3:41 cc cc cc|41 cc cc cc|01 00 00 00|42 cc cc cc
	*         'A'       s1{'A',1}               'B'
	*	S1的最宽简单成员的类型为int,S3在考虑最宽简单类型成员时是将S1“打散”看的,
	*	所以S3的最宽简单类型为int,这样,通过S3定义的变量,其存储空间首地址需要被4整除,
	*	整个sizeof(S3)的值也应该被4整除。
	*	s1偏移量为4,占8个字节
	*	c2的偏移量为12,但总字节数得是4的倍数,所以后面补充字节,共为16个字节
	************************************************************************/

	//八、联合体的sizeof
	/*
	union U
	{
	int i;
	char c;
	S1 s;
	};
	*/
	printf("sizeof(U) is : %d\n",sizeof(U));//8
	//结构体在内存组织上是顺序式的,联合体则是重叠式,各成员共享一段内存,
	//所以整个联合体的sizeof也就是每个成员sizeof的最大值,为8
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值