深入学习指针5,与数组和指针相关的笔试题1(C语言)

前言

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们到评论区友好讨论哟!!

 

好,今天的学习就先到这里,感兴趣的小伙伴不要忘了点一个三连啊,你的支持就是我更新的动力,咱们下期再见。拜拜!! 

 

评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值