深入学习指针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们到评论区友好讨论哟!!

 

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

 

  • 47
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 32
    评论
C语言各种常用关键字详细解释学习,都是总结面试,都是比较好的笔试题。 1 变量 3 1.1 全局变量,局部变量,,常量分别保存在内存中的什么地方? 3 1.2 不同类型的变量,你是否知道其作用域? 3 1.3 全局变量和局部变量是否可以重名?你是否在这样做? 3 1.4 局部变量在函数退出后是否有效,为什么? 3 1.5 全局变量为什么不允许定义在头文件中?有何危害? 3 2 Static 4 2.1 static的三个主要作用是什么? 4 2.2 static的修饰的局部变量是保存在什么地方的?全局变量哪? 5 2.3 static修饰的全局变量和函数,在其他的文件中是否可以访问?如何访问? 5 2.4 你知道static是c语言中实现封装和隐藏的利器吗?你是否经常使用? 5 2.5 定义在不同源文件中的static全局变量,编译器是否允许他们的变量名称相同? 5 2.6 你是否知道auto、extern、register、volatile、restrict、inline的用法? 6 3 const 6 3.1 你是否经常使用const来表明不能够被更改的变量? 6 3.2 你是否经常使用const常量来代替宏? 6 3.3 下面四种情况,你知道是各表示什么意思吗? 6 3.4 你知道const常量如何初始化吗? 7 4 enum枚举 7 4.1 到底enum所定义出来的类型是一个什么样的类型呢? 7 4.2 作为一个用户自定义的类型其所占用的内存空间是多少呢? 8 4.3 是否可以指定枚举中各项的值? 8 4.4 如果不指定值,枚举的第一个值是多少? 8 4.5 枚举的值是否可以是负数? 8 4.6 定义枚举的时候,你是否专门定义了枚举的最小值和最大值? 9 5 switch 9 5.1 switch(c)中的c的数据类型有哪些? 9 5.2 你是否在所有的switch中都加了default语句? 9 5.3 是否在所有的case中都加了break语句(一般情况的做法)?如果你不加break,将会发生什么? 9 6 sizeof 9 6.1 对于字符数组,strlen和sizeof的值是否相同? 9 6.2 Sizeof本质上是什么?函数?宏?其他? 9 6.3 Sizeof的返回值是什么类型? 10 7 动态分配内存 10 7.1 动态分配的内存是保存在什么地方的? 10 7.2 什么情况下使用动态分配内存? 10 7.3 动态申请内存一定要释放,否则会内存泄露。你是否使用过内存检测工具? 10 8 字符串 10 8.1 strlen()函数的返回值是什么类型的? 10 8.2 字符串strlen() 的值,是否和他占据的内存空间相同? 10 8.3 你是否知道strcpy 函数存在的潜在风险?如何避免? 11 8.4 如果一个字符串没有字符串结束符,而调用str 开头的库函数,会发生什么? ?? 11 8.5 Strcpy(),strcat(),strcmp(),strncpy(),strncat(),strncmp()内部到底是如何运行的?这些函数到底对源字符串和目标字符串做了些什么?你是否观察过它们运行时两个字符串内存的变化? 11 8.6 上面这些函数使用时,各有哪些需要注意的地方? 11 8.7 你会几种字符串查找操作? 11 8.8 C语言中有字符串这个数据类型吗? 11 8.9 对字符串进行操作的时候,是否为字符串结尾符预留存储位置?不然的话容易造成非常访问内存。 11 9 数组 12 9.1 你肯定知道,定义“int a[10]; ”, a[10] 这个元素是无效的。 12 9.2 你知道几种数组初始化的方法? 12 9.3 数组指针有千丝万缕的联系而又不同,你是否对他们在不同情况下的使用进行过详细的总结? 12 9.4 “int calendar[10][20]; ”,这是一个什么样的数组?它拥有 10 数组类型的元素,还是 20 个? 12 9.5 “int a[10]; ”,数组名 a 在本质上是一个什么?你是否打印过 a 的值? 12 9.6 你知道几种获取数组某元素的方法? 12 9.7 指针数组相同吗?什么时候相同?什么时候不同? 12 9.8 用指针和下标访问数组元素,那种方式更快? 16 10 结构体 16 10.1 你知道什么是位域结构体吗?如何定义它?如何使用它? 16 10.2 你知道字节对齐对结构体占用内存空间大小的影响吗?如何计算结构体占用内存的小? 17 11 宏 19 11.1 你知道宏的本质是什么吗?函数?语句?类型定义?或者其他? 19 11.2 你知道语言设计者为什么设计宏吗?这些原因目前是否仍然成立? 19 11.3 你会设计带有参数的宏吗? 19 11.4 你知道使用宏的参数的的时候的注意事项吗? 19 11.5 你会设计带有可变参数的宏吗? 19 11.6 你知道使用宏有什么劣势吗? 20 11.7 你有没有更好的替代方案? 20 11.8 为什么说宏定义不好? 21 12 如何避免对同一头文件的多次include? 22 13 什么是声明,什么是定义? 22 14 你是否会运用c语言声明的优先级规则? 23 15 什么是预编译,何时需要预编译? 23 Total time: 90 minutes 23 16 指针数组数组指针的区别? 30 16.1 指针的声明 30 16.1.1 一维数组 31 16.1.2 多维数组 32 16.1.3 指针数组 33 16.1.4 指针指针 33

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值