前言
Hello,亲爱的小伙伴们,我又来了,,今天呢我们一起来学习一下C语言关于数组和指针的部分经典题目。如果觉得不错的话不要忘了点赞,收藏、关注,你的支持就是我更新的最大动力!!
好,废话不多说,开始我们今天的正题!!
1.sizeof和strlen的对比
1.1 sizeof
在学习操作符的时候,我们学习了sizeof,sizeof是计算变量所占内存空间大小的,单位是字节,如果操作数是类型的话,计算的是所用类型创建变量的占用空间的大小。
sizeof只关注内存空间的大小,不在乎内存中存了什么。
比如:
#inculde <stdio.h>int main(){int a = 10;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);printf("%d\n", sizeof(int));return 0;}
1.2 strlen
strlen是C语言的库函数,功能是求字符串的长度。原型是:
size_t strlen ( const char * str );
统计的是聪strlen函数的参数str中的这个地址向后,\0之前的字符串中的字符个数。
strlen会一直计数,知道找到 \0 ,可以越界查找!!
也就是说,strlen函数会关注str所指向的字符串的内容!!
由此,我们比较可得:
2.数组和指针笔试题的讲解
然后有了上面的知识基础,我们就能来看看这些题了
2.1 一维数组
int a[] = {1,2,3,4};printf("%d\n",sizeof(a));printf("%d\n",sizeof(a+0));printf("%d\n",sizeof(*a));printf("%d\n",sizeof(a+1));printf("%d\n",sizeof(a[1]));printf("%d\n",sizeof(&a));printf("%d\n",sizeof(*&a));printf("%d\n",sizeof(&a+1));printf("%d\n",sizeof(&a[0]));printf("%d\n",sizeof(&a[0]+1));
我们可以更具之前学过的知识来判断,这些语句的运行结果分别是是什么呢?
1.我们可知,a为一个一维数组,直接的a在大多数的情况 表示首元素的地址,但有例外,就像第一条语句一样,在操作符sizeof中,a就指代整个数组,计算的是整个数组的大小,单位为字节,所以:
第一条语句的运行结果为:16
2.第二个语句显然不是单独的数组名出现在sizeof中,所以a+0指代的是数组首元素的地址,
地址的所占内存空间大小因平台而异,在VS2022中大致就两种情况 :
4 or 8
运行结果为:4 / 8
3.第三条语句 *a指代的就是整个数组的首元素,所以:
结果为 :4
4. printf("%d\n",sizeof(a+1));
这里a + 1指代的就是第二个元素的地址,故情况与第二条一致!!
4 or 8
5. printf("%d\n",sizeof(a[1]));
a[1] ---->*(a + 1),即为一维数组的第二个元素
4
6.printf("%d\n",sizeof(&a));
由于&a为整个数组的地址,所以:
4 / 8
7. printf("%d\n",sizeof(*&a));
在这里 解引用+取地址可以相互抵消,就相当于计算整个数组内存占用的大小:
16
8. printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));
这三条本质上都是计算的地址的所占空间大小:
4 / 8
好有了上面的基础,大家能不能试着计算,下面语句的运算结果呢?
char arr[] = {'a','b','c','d','e','f'};printf("%d\n", sizeof(arr));printf("%d\n", sizeof(arr+0));printf("%d\n", sizeof(*arr));printf("%d\n", sizeof(arr[1]));printf("%d\n", sizeof(&arr));printf("%d\n", sizeof(&arr+1));printf("%d\n", sizeof(&arr[0]+1));
好,这些题大家都做对了几道呢 ,这些语句的分析方法与上面的题相似,这里就不再赘述,有问题的小伙伴可以在品论区友好交流哟。
接下来我们再看下面的代码:
char arr[] = {'a','b','c','d','e','f'};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));
大家先好好看看,能不能找到答案。
上面我有提到,strlen函数在访问计数字符串时,只有遇到 ‘\0'时,才会停止,否则会出现越界访问的问题
现在我们可以先来看看运行后的结果:
咦,为什么会这样呢?
在上面的字符数组中没有存放,‘\0'
哦,我们现在知道了,在发生越界访问时,要遇到了’/0‘,strlen函数就会停止计数,那什么时候strlen函数会停下来呢,这个我们就不知道了,看因为在内存中,可能会有存储在某些位置的'\0'
使strlen函数停下来,故此时返回的随机值!!
那为什么到第三条语句的时候就出现了问题,无法运行出结果呢?
这个我们就可以从strlen函数的功能结构入手了:
看到这里我们可以了解到,strlen函数是通过访问地址来往后读取·字符串的,而第三条语句使将数组的首元素给了strlen函数,函数会将传给他的内容当作地址去访问, 而 a 这个字符作为地址是无效的,于是就不能得到结果!! 第三条与第四条语句都是一样的原理!!
那后面的三条语句又是怎么回事呢?
上面我们也知道了,&arr在这里就指代整个数组的地址,得到这个地址后strlen函数会逐字节访问,故效果和传给strlen函数arr数组的首地址相同。
倒数第二条语句 &arr + 1,则就相当&arr跳过了整个arr数组的大小个字节,因为arr有6个元素,故可以得到答案。
最后一条语句就十分简单了,传给strlen函数的是数组第二个元素的地址,故得到的结果会少一个。
好,接下来大家可以看看下面的代码:
char arr[] = "abcdef";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))
怎么样大加能够看出答案吗,其实这些语句与上面的代码分析逻辑基本相符,但是“” 包住的字符串在末尾会自动为字符串添加上 ' \0'因此就不会再出现上面的越界问题。
那大家就自己练习一下吧。
那我就先去喝口茶~~
大家做出来了吗?作者菌就先将大安放到这了,有问题的话,欢迎uu们到评论区友好讨论哟!!
好,今天的学习就先到这里,感兴趣的小伙伴不要忘了点一个三连啊,你的支持就是我更新的动力,咱们下期再见。拜拜!!