C语言:关键字---sizeof(计算存储空间)

C语言32个关键字
有32个关键字详细说明,还有跳转链接!

sizeof是一个“披着函数皮的关键字”,是一种单目操作符,绝对不是函数。


一、sizeof 简介

1. 一般形式

sizeof(对象);
sizeof(object);

注意:除了数据类型,其他的对象可以不用括号,这也是sizeof不是函数最有力的证明。

2. 功能

返回一个对象在内存中所占中的存储空间,以字节为单位计数。
对象包括:变量、基本数据类型、数组、指针和结构体等。

二、sizeof 用法

1. 基本数据类型

数据类型数据类型符占用字节数数值范围
整型int2/4同短整型/长整型
短整型short2-32768~32767
长整形long4-2的31次方~2的31次方-1
单精度浮点型float4-10的38次方~10的38次方
双精度浮点型double8-10的308次方~10的308次方
字符型char1-128~127

注意:整型int的字节数由系统决定的,在16位系统中占2个字节,在32位系统中占4个字节
具体代码如下:

#include <stdio.h>

int main(void)
{
	printf("int=%d,short=%d,long=%d,float=%d,double=%d,char=%d\n",
	sizeof(int),sizeof(short),sizeof(long),sizeof(float),sizeof(double),sizeof(char));
	
	return 0;
}

运行代码如下:

int=4,short=2,long=4,float=4,double=8,char=1

2. 变量

由基本数据类型定义的变量,所占用的内存空间,与其基本类型的占用内存一样。
具体代码如下:

#include <stdio.h>

	int 	a;
	short 	b;
	long  	c;
 	float	d;
 	double  e;
 	char    f;

int main(void)
{
	printf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",
	sizeof(a), sizeof(b), sizeof(c),sizeof(d),sizeof(e),sizeof(f));
	
	return 0;
}

运行结果如下:

a=4,b=2,c=4,d=4,e=8,f=1

3. 指针

指针是一个占据存储空间的实体在这一段空间起始位置的相对距离值。在C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的首地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。
指针变量是用来存放内存地址的变量,不同类型的指针变量所占用的存储单元长度是相同的,也就是说所有数据的存放地址的长度是相同的,由计算机的位数决定。
通常情况下,指针变量的sizeof返回值:32位系统—4字节,64位系统—8字节。
具体代码如下:

#include <stdio.h>

	int 	*a={1,2,3,4,5};
	short 	*b={1,2,3,4,5};
	long  	*c={1,2,3,4,5};
 	float	*d={1,2,3,4,5};
 	double  *e={1,2,3,4,5};
 	char    *f="12345";
 	void(*p);	//参数指针 

int main(void)
{
	printf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d,p=%d\n",
	sizeof(a), sizeof(b), sizeof(c),sizeof(d),sizeof(e),sizeof(f),sizeof(p));
	return 0;
}

运行结果如下:

a=4,b=4,c=4,d=4,e=4,f=4,p=4

4. 数组

数组的sizeof值等于数组所占用的内存字节数,并不是数组元素的个数。
具体代码如下:

#include <stdio.h>

	int 	a[]={1,2,3,4,5};
	short 	b[]={1,2,3,4,5};
	long  	c[]={1,2,3,4,5};
 	float	d[]={1,2,3,4,5};
 	double  e[]={1,2,3,4,5};
 	char    f[]="12345";

int main(void)
{
	printf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",
	sizeof(a), sizeof(b), sizeof(c),sizeof(d),sizeof(e),sizeof(f));
	
	return 0;
}

运行结果如下:

a=20,b=10,c=20,d=20,e=40,f=6

注意:字符串的末尾存在一个NULL终止符,所以会多出有一个字节。

如想得到数组的元素个数,有以下两种方法:

  • 总长度/相对应的数据类型长度
  • 总长度/首元素长度

具体代码如下:

#include <stdio.h>

	int 	a[]={1,2,3,4,5};
	short 	b[]={1,2,3,4,5};
	long  	c[]={1,2,3,4,5};
 	float	d[]={1,2,3,4,5};
 	double  e[]={1,2,3,4,5};
 	char    f[]="12345";

int main(void)
{
	printf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",
	sizeof(a)/sizeof(int), sizeof(b)/sizeof(short), sizeof(c)/sizeof(long),sizeof(d)/sizeof(float),sizeof(e)/sizeof(double),sizeof(f)/sizeof(char));

	printf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",
	sizeof(a)/sizeof(a[0]), sizeof(b)/sizeof(b[0]), sizeof(c)/sizeof(c[0]),sizeof(d)/sizeof(d[0]),sizeof(e)/sizeof(e[0]),sizeof(f)/sizeof(f[0]));
	return 0;
}

运行结果如下:

a=5,b=5,c=5,d=5,e=5,f=6
a=5,b=5,c=5,d=5,e=5,f=6

注意:由于字符串的末尾存在一个NULL终止符,会多出有一个字节,计算数组元素个数时,可以减一。

参数数组是一个特殊的存在,由于数组是“传址”的,调用者只需将实参的地址传递过去,所以参数数组自然为指针类型,这样参数数组的sizeof返回值就是指针变量的返回值。
具体代码如下:

#include <stdio.h>

	int 	a[5]={1,2,3,4,5};
	short 	b[5]={1,2,3,4,5};
	long  	c[5]={1,2,3,4,5};
 	float	d[5]={1,2,3,4,5};
 	double  e[5]={1,2,3,4,5};
 	char    f[5]="12345";

void MQ1(char data1[5])
{
	printf("data1=%d\n",sizeof(data1));
} 

void MQ2(char data2[])
{
	printf("data2=%d\n",sizeof(data2));
} 

int main(void)
{
	MQ1(f);
	MQ2(f);
	return 0;
}

运行结果如下:

data1=4
data2=4

5. 结构体

结构体的sizeof值等于结构体所占用的内存字节数。
具体代码如下:

#include <stdio.h>

struct MQ
{
	char    a;
	int 	b;
} data={'a',0x55555555};

int main(void)
{
	printf("struct=%d\n",sizeof(data));
	return 0;
}

运行结果:

struct=8

一个char占1个字节,一个int占4个字节,那么加起来就应该是5,为什么运行结果是8?
由于字节对齐的原因,为此编译器默认会对结构体进行处理,让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,以此类推。这样,两个数中间就可能需要加入填充字节,所以整个结构体的sizeof值就增长了。
看一下填充情况,具体运行代码如下:

#include <stdio.h>

struct MQ
{
	char    a;
	int 	b;
} data={'a',0x55555555};

int main(void)
{
	printf("struct=%d\n",sizeof(data));
	
	adder=&data;//获取结构体首地址
	for(i=0;i<sizeof(data);i++)
	printf("%x ",*(unsigned __int8*)(adder+i));
	printf("\n");
	return 0;
}

运行结果如下:

struct=8
61 0 0 0 55 55 55 55
//有三个填充字节。

举个例子,说明一下计算内存的方法和思路。
具体代码如下:

#include <stdio.h>

struct MQ
{
	char    a;
	int 	b;
	
	char	c;
	short 	d;
	
	short 	e;
	char	f;
	
	short 	g;
	int  	h;
	
	char    k;
} data={'a',0x55555555,'b',0x1111,0x2222,'c',0x3333,0x44444444,'d'};//这样定义有利于判断填充字节 

int main(void)
{
	int i=0,adder=0;
	printf("struct=%d\n",sizeof(data));

	adder=&data;
	for(i=0;i<sizeof(data);i++)
	printf("%x ",*(unsigned __int8*)(adder+i));
	printf("\n");

	return 0;
}

运行结果如下:

struct=28
61 0 0 0 55 55 55 55 62 0 11 11 22 22 63 0 33 33 0 0 44 44 44 44 64 0 0 0

计算思路:
变量偏移量必须是变量所占内存的整数倍,否则填充0对齐。
结构体的总内存必须是最长变量内存的整数倍,否则填充0对齐。

变量偏移量内存数据(hex)
char a0461 0 0 0
int b4455 55 55 55
char c8262 0
short d10211 11
short e12222 22
char f14263 0
short g16433 33 0 0
int h20444 44 44 44
char k24464 0 0 0

内存总和28=最后变量的偏移量24+最后变量占的内存4


以上就是结构体的sizeof值的计算思路,有些C语言的考试题会遇见,其他情况直接调用程序就可以轻松得到答案。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

根号五

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值