指针篇:深入理解sizeof和strlen

✨✨小新课堂开课了,欢迎欢迎~✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:http://t.csdnimg.cn/Oytke

小新的主页:编程版小新-CSDN博客

在深入理解sizeof和strlen之前,我们先对其进行简单的介绍。

在学习操作符的时候,我们学习了 sizeof , sizeof 是用来计算变量所占内存内存空间⼤⼩的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩。一定要注意的是sizeof只计算类型所占内存的大小,不关注内存中存放的什么数据。

strlen其实是一个函数,用来计算字符串长度,在使用该函数的时候要包含头文<string.h>,计算的过程中遇到'\0'停止,如果没有'\0'就有可能会出现越界访问。因为这篇文章是用指针来理解strlen,在这里就和大家提一下 strlen的函数原型: size_t strlen ( const char * str );

为了方便大家的理解,给大家准备了表格进行对比:

sizeofstrlen
1.sizeof是操作符1.库函数,使用前要包含头文件
2.计算内存所占空间的大小2.计算'\0'之前字符的个数
3.不管内存中存放的什么数据3.如果没有'\0'可能会出现越界访问

接下来我们进入正文,这里要补充到到一些知识点,首先是一般数组名代表数组首元素的地址,只有在两种情况下代表的是整个数组的地址:1.sizeof(arr)数组名单独放在sizeof内部   2.&arr这时取出的地址是整个数组的地址。一定要切记这两点,把握好这两点才能避免很多错误。

无论是一维数组还是二维数组在内存中都是连续存放的

arr[3][4]
0123
01234
15678
29101112

这是我们以为的二维数组在内存中的存放方式,实际情况并非如此。

第一行第二行第三行
123456789101112
arr[0]arr[1]arr[3]

这才是二维数组在内存中存放的实际情况。 

另外还要补充的是:指针 - 指针  绝对值 得到是指针与指针之间的元素个数;类型加减常数要看是什么类型,比如整型+1跳过4个字节。

下面请看整体的例子:

#include<stdio.h>
int main()
{
	int arr[3][4] = { 0 };//arr是数组名,arr[0]是第一行的数组名
	printf("%zd\n", sizeof(arr));//arr单独放在sizeof内部,计算的是数组的大小,单位是字节,12*4==48
	printf("%zd\n", sizeof(arr[0][0]));//arr没有单独放在sizeof内部,也没有&arr,此时arr[0][0]表示数组
	//首元素的地址,是地址就是4/8个字节
	printf("%zd\n", sizeof(arr[0]));//arr[0]是第一行的数组名,数组名单独放在sizeof内部,计算第一行数组的大小
	//是16个字节
	printf("%zd\n", sizeof(arr[0] + 1));//arr[0]没有单独放在sizeof内部,arr[0]表示数组首元素的地址,就是arr[0][0]的地址,+1跳过4个
	//字节,就是arr[0][1]的地址,是地址,就是4/8个字节
	printf("%zd\n", sizeof(*(arr[0] + 1)));//arr[0]没有单独放在sizeof内部,arr[0]表示数组首元素的地址,+1
	//跳过4个字节,就是arr[0][1]的地址,*(解引用)后,就是第一行第二个元素,4个字节
	printf("%zd\n", sizeof(arr + 1));//arr没有单独放在sizeof内部,表示数组首元素的地址,是二位数组首元素的地址,
	//是第一行的地址,+1,跳过一行,表示第二行的地址,是地址就是4/8个字节
	printf("%zd\n", sizeof(*(arr + 1)));//arr+1表示第二行的地址,*后,就是第二行,计算的是第二行的大小,16个字节
	printf("%zd\n", sizeof(&arr[0] + 1));//arr[0]是第一行,&arr[0]取出的是第一行的地址,+1是第二行的地址,是
	//地址就是4/8个字节
	printf("%zd\n", sizeof(*(&arr[0] + 1)));//*后,得到的是第二行,计算第二行的大小,16个字节
	printf("%zd\n", sizeof(*arr));//arr没有单独放在sizeof内,是数组首元素的地址,是二维数组首元素的地址,也
	//就是第一行的地址,*后,计算第一行的大小,16个字节
	printf("%zd\n", sizeof(&arr));//&arr取出的是数组的地址,是地址就是4/8个字节
	printf("%zd\n", sizeof(*&arr));//*与&相抵消,sizeof(*&arr)==sizeof(arr),计算的是数组的大小,48个字节
	printf("%zd\n", sizeof(arr[3]));//arr[3]无需真实存在,仅仅需要类型的推断就能计算出长度
	//arr[3]是第四行的数组名,数组名单独放在sizeof内,计算第四行的大小,16个字节

char* p = "abcdef";//p是指针变量,里面存放的首元素'a'的地址,知道了'a'的地址就能找到整个字符串
printf("%zd\n", sizeof(p));//4/8
printf("%zd\n", sizeof(p + 1));//+1后,就是'b'的地址,是地址就是4/8个字节
printf("%zd\n", sizeof(*p));//p的类型是conest char *,*后,就是char类型,结果是1个字节
printf("%zd\n", sizeof(p[0]));//p[0]是首元素的地址,是地址就是4/8个字节
printf("%zd\n", sizeof(&p));//&p,取出的是p的地址,是地址就是4/8个字节
printf("%zd\n", sizeof(&p + 1));//&p+1,就是跳过指针变量p的地址的后一个地址,是地址,就是4/8个字节
printf("%zd\n", sizeof(&p[0] + 1));//+1后,是第二个元素的地址,是地址就是4/8个字节


	return 0;
}
#include<stdio.h>
int main()
{
   char arr[] = { 'a','b','c','d','e','f' };//没有'\0'系列
printf("%d\n", strlen(arr));//arr是数组名,是数组首元素的地址,数组中没有'\0',就有可能越界访问,结果是随机的
printf("%d\n", strlen(arr + 0));//arr+0是数组首元素的地址,数组中没有'\0',就有可能越界访问,结果是随机的
printf("%d\n", strlen(*arr));//arr是数组首元素的地址,*后,就是'a','a'的ascii码值是97,就相当于把97当作
//地址传给了strlen,strlen得到的是野指针,代码有问题
printf("%d\n", strlen(arr[1]));//arr[1]是数组中的第二个字符'b','b'的ascii码值是98,就相当于把98当作地址
//传给了strlen,strlen得到的是野指针,代码有问题
printf("%d\n", strlen(&arr));//&arr,取出的是整个数组的地址,起始位置是数组的第一个元素,结果是随机值
printf("%d\n", strlen(&arr + 1));//+1,跳过整个数组,因为没有'\0',结果还是随机值
printf("%d\n", strlen(&arr[0] + 1));//&arr[0],是数组首元素的地址,+1,是第二个元素的地址,结果还是随机值

char arr[] = "abcdef";//存在'\0'系列
printf("%d\n", strlen(arr));//arr是数组名,是数组首元素的地址,结果是6
printf("%d\n", strlen(arr + 0));//arr+0是数组首元素的地址,结果是6
printf("%d\n", strlen(*arr));//arr是数组名,是数组首元素的地址,*后,是数组中的第一个元素,结果是6
printf("%d\n", strlen(arr[1]));//arr[1]是数组中第二个元素的地址,结果是5
printf("%d\n", strlen(&arr));//&arr,取出的是整个数组的地址,起始位置是数组首元素,结果是6
printf("%d\n", strlen(&arr + 1));//+1,跳过整个数组,也就跳过了原本数组中的'\0',结果是随机值
printf("%d\n", strlen(&arr[0] + 1));//+1,跳过一个字节,来到数组的第二个元素,是第二个元素的地址,结果是5

char* p = "abcdef";//有'\0'存在,p是指针变量,里面存放的首元素'a'的地址,知道了'a'的地址就能找到整个字符串
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5,类比为p[0]+1
printf("%d\n", strlen(*p));//*p->'a'->97->err
printf("%d\n", strlen(p[0]));//6
printf("%d\n", strlen(&p));//&p,取出的是p的地址,就和字符串"abcdef"关系就不大了,从p这个指针变量的
//起始位置开始向后数,结果是随机值
printf("%d\n", strlen(&p + 1));//随机值
printf("%d\n", strlen(&p[0] + 1));//5


   return 0;
}

通过以上很多例子,你有没有对sizeof和strlen有更加清晰的认识,后期会更新指针的内容,以及字符函数和字符串函数的知识,希望大家可以一起进步 ,感谢大家的支持~

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值