前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >sizeof和strlen的对⽐及例题

sizeof和strlen的对⽐及例题

作者头像
ahao
发布2024-03-19 18:50:43
580
发布2024-03-19 18:50:43
举报
文章被收录于专栏:学习学习
sizeof

在学习操作符的时候,我们学习了 sizeof , sizeof 计算变量所占内存内存空间⼤⼩的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩ 例如:

代码语言:javascript
复制
int main()
{
	int ret1 = sizeof(int);
	int a = 0;
	int ret2 = sizeof(ret2);
	printf("ret1 = %d\n", ret1);
	printf("ret2 = %d\n", ret2);
	return 0;
}

代码跑起来ret1和ret2输出的值都等于4 同时,sizeof 只关注占⽤内存空间⼤⼩,不在乎内存中存放什么数据 例如: 下列代码输出的三个值都等于4

代码语言:javascript
复制
int main()
{
 int a = 10;
 printf("%d\n", sizeof(a));
 printf("%d\n", sizeof a);
 printf("%d\n", sizeof(int));
 return 0;
}
strlen

strlen 是C语⾔库函数,功能是求字符串⻓度,函数原型如下: strlen函数不许要改变字符串,所以可以加上const

代码语言:javascript
复制
size_t strlen ( const char * str )

strlen返回的是从str字符串的其实位置开始向后,“\0”前的字符个数 strlen 函数会⼀直向后找 \0 字符,直到找到为⽌,所以可能存在越界查找 例如:

代码语言:javascript
复制
	char arr[] = "hello world";
	int ret = strlen(arr);
	printf("%d\n", ret);

ret的值等于多少呢,大家可以思考一下 思考完了吧! 大家要注意,空格也是字符,所以ret等于11! 下面还有一个代码:

代码语言:javascript
复制
	char arr[] = "a,b,c,d";
	int ret = strlen(arr);
	printf("%d\n", ret);
	return 0;

可能大部分同学第一眼会觉得ret的值是4 但是结果如下:

因为这个arr存储的单个的字符,并不是字符串,arr中并没有“\0”,所以只能输出随机值

sizeof和strlen的区别

首先看一段代码: 思考一下代码运行结果

代码语言:javascript
复制
#include <stdio.h>
int main()
{
 char arr1[3] = {'a', 'b', 'c'};
 char arr2[] = "abc";
 printf("%d\n", strlen(arr1));
 printf("%d\n", strlen(arr2));
 printf("%d\n", sizeof(arr1));
 printf("%d\n", sizeof(arr1));
 return 0;
}

代码结果输出如下

为什么呢,大家可能对于sizeof(arr2)的值会有疑惑 详解如下

代码语言:javascript
复制
#include <stdio.h>
int main()
{
 char arr1[3] = {'a', 'b', 'c'};
 char arr2[] = "abc";
 printf("%d\n", strlen(arr1));//arr1没有\0,输出随机值
 printf("%d\n", strlen(arr2));//字符串结尾有\0,输出3
 printf("%d\n", sizeof(arr1));//三个字符占三个字节的大小,输出3
 printf("%d\n", sizeof(arr1));//字符串结尾的\0也是一个字符,占一个字节的大小,输出4
 return 0;
}

下面我们对于二者做一个对比: sizeof

代码语言:javascript
复制
1. sizeof是操作符
2. sizeof计算操作数所占内存的⼤⼩,单位是字节
3. 不关注内存中存放什么数据

strlen

代码语言:javascript
复制
1. strlen是库函数,使⽤需要包含头⽂件 string.h
2. srtlen是求字符串⻓度的,统计的是 \0 之前字符的隔个数
3. 关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可能越界
例题分析
代码语言:javascript
复制
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//四个整形数据,大小为16字节
	printf("%d\n", sizeof(a + 0));
	//数组名等于数组首地址,+0后也是一个地址,地址就是指针,指针的大小为4/8个字节在x86/x64环境下
	printf("%d\n", sizeof(*a));//对数组的首地址解引用就是数组首元素,大小为4个字节
	printf("%d\n", sizeof(a + 1));
	//数组名等于数组首地址,+1后也是一个地址,地址就是指针,指针的大小为4/8在x86/x64环境下
	printf("%d\n", sizeof(a[1]));//arr[1]就是首元素,大小为4个字节
	printf("%d\n", sizeof(&a));
	//&数组名是取整个数组的地址,但是指针的大小就是4或8各个字节的大小
	printf("%d\n", sizeof(*&a));//取地址整个数组后解引用就是整个数组的内容,大小为16字节
	printf("%d\n", sizeof(&a + 1));//取地址+1仍然是地址,大小为4/8字节
	printf("%d\n", sizeof(&a[0]));//同上
	printf("%d\n", sizeof(&a[0] + 1));//同上

大家要记住,其实地址就是指针,而指针的大小只能为4或者8个字节

代码语言:javascript
复制
char arr[] = {'a','b','c','d','e'};
printf("%d\n", sizeof(arr));//5个字符的大小为五个字节
printf("%d\n", sizeof(arr+0));//地址的大小为4/8个字节
printf("%d\n", sizeof(*arr));//arr是首元素的地址,解引用就是首元素,大小为1字节
printf("%d\n", sizeof(arr[1]));//首元素大小,1字节
printf("%d\n", sizeof(&arr));//地址的大小为4/8个字节
printf("%d\n", sizeof(&arr+1));//同上
printf("%d\n", sizeof(&arr[0]+1));//同上

下面在同样的数组内容下,我们用strlen来测试

代码语言:javascript
复制
	char arr[] = { 'a','b','c','d','e' };
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));

大家跑起来就会发现 在printf(“%d\n”, strlen(arr));printf(“%d\n”, strlen(arr[1])); 这两行发生了中断,但是将其注释后可以跑动起来,这是为何呢? 大家可以发现,这两行arr和arr[1]都是字符元素,但是我们知道strlen函数所处理的必须为字符型指针,所以出现中断 其他行都是由于arr中没有“\0”,所以其他行都是输出随机值

通过上面的代码,我们可以总结出一个规律:

代码语言:javascript
复制
1.sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。
2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表⽰⾸元素的地址

此外,大家要注意: 再数组中: &(数组名)+1是跳过整个数组 &(数组名+1)是跳过第一个元素

代码语言:javascript
复制
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//字符串结尾有\0,一共7字节
printf("%d\n", sizeof(arr+0));//指针大小4/8字节
printf("%d\n", sizeof(*arr));//首元素字符a,大小1字节
printf("%d\n", sizeof(arr[1]));//同上
printf("%d\n", sizeof(&arr));//指针大小4/8字节
printf("%d\n", sizeof(&arr+1));//同上
printf("%d\n", sizeof(&arr[0]+1));//同上
代码语言:javascript
复制
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//六个字符,输出6
	printf("%d\n", strlen(arr + 0));//同上,arr+0依然是arr
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));//六个字符,输出6
	printf("%d\n", strlen(&arr + 1));//跳过整个数组,随机值
	printf("%d\n", strlen(&arr[0] + 1));
	//跳过第一个字符a后,从第二个字符b开始遍历,五个字符,输出5

第三行和第四行出现了同样的问题,注释掉输出结果

代码语言:javascript
复制
	char* p = "abcdef";
	printf("%d\n", sizeof(p));//p是字符a的地址,指针大小为4/8
	printf("%d\n", sizeof(p + 1));//地址+1仍然为指针,大小为4/8
	printf("%d\n", sizeof(*p));//对a的地址进行解引用,就是a的大小,1字节
	printf("%d\n", sizeof(p[0]));//p[0]就是a,大小为1字节
	printf("%d\n", sizeof(&p));//&数组名,依然是指针,大小为4/8
	printf("%d\n", sizeof(&p + 1));//同上
	printf("%d\n", sizeof(&p[0] + 1));//同上

注意:char* p = "abcdef"是将abcdef中a的地址存入p中,也就是首地址

代码语言:javascript
复制
	char* p = "abcdef";
	printf("%d\n", strlen(p));//p是首地址,六个元素,大小6个字节
	printf("%d\n", strlen(p + 1));//p+1开始遍历,五个元素,大小5个字节
	printf("%d\n", strlen(*p));
	printf("%d\n", strlen(p[0]));
	printf("%d\n", strlen(&p));//六个元素,大小6个字节
	printf("%d\n", strlen(&p + 1));//&p是取p的地址,而p又是a的地址,p的地址是未知的,随机值
	printf("%d\n", strlen(&p[0] + 1));//从第二个字符开始遍历,五个元素,大小5个字节

上述代码的三四行代码依旧是老问题,strlen里面只能为指针

代码语言:javascript
复制
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//size(a)是取整个二维数组,12个int类型,48个字节
	printf("%d\n", sizeof(a[0][0]));//代表首元素的地址,4个字节
	printf("%d\n", sizeof(a[0]));//a[0]指向的第一行的所有元素,4个元素,14个字节
	printf("%d\n", sizeof(a[0] + 1));//指针大小为4/8字节
	printf("%d\n", sizeof(*(a[0] + 1)));//对a[0]+1再解引用,即第一行第二个元素的大小,4个字节
	printf("%d\n", sizeof(a + 1));//地址+1依然为地址,大小为4/8个字节
	printf("%d\n", sizeof(*(a + 1)));//首地址+1后再解引用,第二行所有元素,16个字节
	printf("%d\n", sizeof(&a[0] + 1));//地址+1依然为地址,大小为4/8个字节
	printf("%d\n", sizeof(*(&a[0] + 1)));//第一行第一个元素+1后解引用,代表第二行所有元素,16个字节
	printf("%d\n", sizeof(*a));//,对a[0][0]解引用,第一行所有元素,16个字节
	printf("%d\n", sizeof(a[3]));//虽然第三行不存在,但是我们依然知道一行有四个int类型的空间,16字节

二维数组中,&a[0]+1后为第二行的首元素,即a[1][0]

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • sizeof
  • strlen
  • sizeof和strlen的区别
  • 例题分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档