区分sizeof和strlen

"本文详细介绍了C语言中sizeof和strlen的区别和用法,包括sizeof用于计算变量、数组、指针所占内存大小,以及strlen用于计算字符串长度。通过实例分析了sizeof在整型数组、字符数组、字符指针、二维数组中的应用,以及strlen在处理字符数组和字符指针时的注意事项。文章强调了sizeof在编译时计算,strlen在运行时计算到''为止的特点。"
摘要由CSDN通过智能技术生成


(一)关于sizeof和strlen

  sizeof是操作符(不是函数),单位是字节,作用是求变量所占空间的大小或者求类型创建的变量所占空间的大小,和内存中放什么数据没有关系

#include <stdio.h>
int main()
{
	int a = 10;
	short b = 20;
	printf("%d\n", sizeof(a));//整型变量在内存中占4个字节
	printf("%d\n", sizeof(int));//整型类型在内存中占4个字节
	printf("%d\n", sizeof(char));//字符型类型在内存中占1个字节
	
	printf("%d\n", sizeof(b));//短整型类型在内存中占2个字节
	printf("%d\n", sizeof(b = a + 5));//int赋值给short类型,结果还是short
	printf("%d\n", b);//得数还是20
	return 0;
}

  特别注意最后一个输出,在倒数第二个输出的时候,a+5赋值给了b,但是最终b的打印结果任然是20。这与sizeof操作符有关,sizeof内部的运算符是不参与运算的,因为由源文件变成可执行程序的过程中,先编译再链接,最后生成可执行程序,生成可执行程序后运行代码,然而,在编译阶段就已经知道sizeof(b = a + 5)的结果是2了,所以之后根本没有机会执行后面的运算。


  strlen是库函数,计算的是字符串的长度,需要关注内存中是否有“\0”,得到的是“\0”之前出现的的字符的个数

#include <stdio.h>
int main()
{
	char arr1[] = "abcdef";//元素个数为7,最后一位自动补为“\0”
	char arr2[5] = { 'a','b','c','d','e' };//素个数6,没有“\0”
	printf("%d\n", strlen(arr1));//输出为6
	printf("%d\n", strlen("abcde"));//等价于arr1
	printf("%d\n", strlen(arr2));//输出为随机值
	return 0;
}

(二)sizeof和数组

  下面来分析几个例子。

整型数组

//整型数组
#include <stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	//特例,表示整个数组元素的大小,输出为16
	
	printf("%d\n", sizeof(a + 0));
	//这里的a表示首元素地址,+0后不变,地址是4/8个字节
	
	printf("%d\n", sizeof(*a));
	//a是首元素的地址,*a为首元素,大小为4个字节,*a等价于*(a+0)等价于a[0]
	
	printf("%d\n", sizeof(a + 1));
	//a是首元素的地址,a+1是第二个元素地址,大小为4/8个字节
	
	printf("%d\n", sizeof(a[1]));
	//第二个元素,大小为4个字节
	
	printf("%d\n", sizeof(&a));
	//&a是整个数组的地址,地址的大小是4/8个字节
	
	printf("%d\n", sizeof(*&a));
	//&a是整个数组的地址,*&a,解引用之后是整个数组的大小,输出为16
	
	printf("%d\n", sizeof(&a + 1));
	//&a是整个数组的地址,+1后移动一个数组的位置,得到的是地址,大小是4/8
	
	printf("%d\n", sizeof(&a[0]));
	//首元素的地址,大小是4/8
	
	printf("%d\n", sizeof(&a[0] + 1));
	//首元素的地址+1,即第二个元素的地址,大小是4/8
	return 0;
}

  数组名不表示首元素地址的特例1.sizeof(数组名),表示整个数组元素的大小
                                                2.&数组名,表示整个数组的地址。

字符数组

//字符数组
#include <stdio.h>
int main()
{
	char arr[]={'a','b','c','d','e','f'};
	printf("%d\n",sizeof(arr));
	//整个数组的大小,输出为6
	
	printf("%d\n",sizeof(arr+0));
	//首元素地址加0,不变,大小是4/8
	
	printf("%d\n",sizeof(*arr));
	//首元素地址解引用,大小是1
	
	printf("%d\n",sizeof(arr[1]));
	//第二个元素,大小是1
	
	printf("%d\n",sizeof(&arr));
	//取的是整个数组的地址,地址,大小为4/8
	
	printf("%d\n",sizeof(&arr+1));
	//整个数组的地址+1,跳过整个数组,还是地址,大小是4/8
	
	printf("%d\n",sizeof(&arr[0]+1));
	//首元素的地址加一,大小是4/8
	return 0;
}
#include <stdio.h>
int main()
{
	char arr[]="abcdef";//7个元素
	printf("%d\n",sizeof(arr));
	//整个数组的大小,输出为7
	
	printf("%d\n",sizeof(arr+0));
	//首元素地址加0,不变,大小是4/8
	
	printf("%d\n",sizeof(*arr));
	//首元素地址解引用,arr[0],大小是1
	
	printf("%d\n",sizeof(arr[1]));
	//第二个元素,大小是1
	
	printf("%d\n",sizeof(&arr));
	//取的是整个数组的地址,地址,大小为4/8
	
	printf("%d\n",sizeof(&arr+1));
	//整个数组的地址+1,跳过整个数组,还是地址,大小是4/8
	
	printf("%d\n",sizeof(&arr[0]+1));
	//首元素的地址加一,大小是4/8
	return 0;
}

字符指针

//字符指针
#include <stdio.h>
int main()
{
	const char*p="abcdef";
	printf("%d\n",sizeof(p));
	//p时字符指针,大小是4/8个字节
	
	printf("%d\n",sizeof(p+1));
	//char*类型的指针加一。跳过一个字节,是b的地址,大小是4/8个字节
	
	printf("%d\n",sizeof(*p));
	//是a,大小是1
	
	printf("%d\n",sizeof(p[0]));
	//等价于*(p+0),还是a的地址,大小是4/8个字节
	
	printf("%d\n",sizeof(&p));
	//指针变量p的地址,大小是4/8
	
	printf("%d\n",sizeof(&p+1));
	//二级指针的地址,大小是4/8
	
	printf("%d\n",sizeof(&p[0]+1));
	//首元素a的地址加一,还是地址,b的地址,大小是4/8个字节
	return 0;
}

  其中注意倒数第二个,&p是一级指针的地址。相当于char** par=&p,sizeof(&p+1)就相当于sizeof(par+1),向前移动四个字节,本质还是地址,大小是4/8。

二维数组

//二维数组
#include <stdio.h>
int main()
{
	int a[3][4]={0};
	printf("%d\n",sizeof(a));
	//整个数组的大小,12*4=48
	
	printf("%d\n",sizeof(a[0][0]));
	//int类型的,输出为4
	
	printf("%d\n",sizeof(a[0]));
	//第一行元素的大小,相当于于一维数组,输出为4*4=16
	
	printf("%d\n",sizeof(a[0]+1));
	//a[0][1],输出为4
	
	printf("%d\n",sizeof(*(a[0]+1)));
	//a[0][1]的地址,大小是4/8个字节
	
	printf("%d\n",sizeof(a+1));
	//a代表首元素(第一行)的地址,a+1是第二行元素的首地址,相当于一维数组,大小是4/8

	printf("%d\n",sizeof(*(a+1)));
	//*(a+1)就是第二行,大小是16

	printf("%d\n",sizeof(&a[0]+1));
	//首元素(第一行)的地址加一,得到的还是第二行的地址,类型是int(*) [4]大小是4/8

	printf("%d\n",sizeof(*(&a[0]+1)));
	//首元素(第一行)地址加一再解引用。即第二行元素,大小是16

	printf("%d\n",sizeof(*a));
	//首元素的地址,解引用,得到首元素(第一行),大小是16

	printf("%d\n",sizeof(a[3]));
	//相当于第四行的数组名,假想存在,并没有真正去访问,得到的是16
	return 0;
}

  注意第四个sizeof(a[0]+1),这个时候的a[0]并没有单独放在sizeof内部,这是只表示第一行首元素的地址,加一后变成第一行第二个元素。

在这里插入图片描述

(三)strlen和数组

字符数组

#include <stdio.h>
int main()
{
	char arr[]={'a','b','c','d','e','f'};
	printf("%d\n",strlen(arr));
	//找不到“\0”,输出随机值
	
	printf("%d\n",strlen(arr+0));
	//首元素地址,随机值
	
	printf("%d\n",strlen(*arr));
	//error野指针,程序运行错误
	
	printf("%d\n",strlen(arr[1]));
	//和上一个类似,error
	
	printf("%d\n",strlen(&arr));
	//arr整个数组的地址,虽然是整个数组,但是数值上和首元素地址相同,相当于第一个,结果为随机值
	
	printf("%d\n",strlen(&arr+1));
	//移动一个数组的大小,输出为随机值,和第一个随机值差6
	
	printf("%d\n",strlen(&arr[0]+1));
	//第二个元素的地址,输出为随机值,和第一个差1
	return 0;
}

  注意第三个strlen(arr),这里的arr就是首元素,对应ASCII值为97,此时的strlen认为传进来的97就是地址,向后访问时就崩溃了,出现问题。

#include <stdio.h>
int main()
{
	char arr[]="abcdfe";
	printf("%d\n",strlen(arr));
	//arr[6]='\0',输出为6
	
	printf("%d\n",strlen(arr+0));
	//首元素地址,输出也为6
	
	printf("%d\n",strlen(*arr));
	//error野指针,程序运行错误,与上一次相同
	
	printf("%d\n",strlen(arr[1]));
	//和上一个类似,error
	
	printf("%d\n",strlen(&arr));
	//arr整个数组的地址,虽然是整个元素,类型不同,但是数值上和首元素地址相同,相当于第一个,结果为6
	
	printf("%d\n",strlen(&arr+1));
	//移动一个数组的大小,输出为随机值
	
	printf("%d\n",strlen(&arr[0]+1));
	//第二个元素的地址,输出为5
	return 0;
}

字符指针

//字符指针
#include <stdio.h>
int main()
{
	char* p="abcdef";
	printf("%d\n",strlen(p));
	//字符串的大小,输出的是6

	printf("%d\n",strlen(p+1));
	//p是a的地址,p+1是b的地址,输出5
	
	printf("%d\n",strlen(*p));
	//把a传进去了,error
	
	printf("%d\n",strlen(p[0]));
	//等价于*(p+0)和上一个相同,error
	
	printf("%d\n",strlen(&p));
	//p的地址,输出随机值
	
	printf("%d\n",strlen(&p+1));
	//和上一个相同,输出随机值
	
	printf("%d\n",strlen(&p[0]+1));
	//a的地址加一,得到b的地址,输出为5
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值