C语言-八道笔试题由浅入深玩转指针 一.笔试题1 -指针与一维数组的关系-值 图解:
二.笔试题2-指针与结构体 注意坑点:整数+1 ->跳过一个字节 执行普通的加减运算 而整形指针+1 ->跳过四个字节 指针+1 的步长取决于指针指向的数据的类型 三.笔试题3-指针与一维数组的关系-址 解析: int *ptr1 = (int *)(&a + 1): 取出数组的地址+1,跳过一个数组,因为&a的类型为数组指针:int(*)[4] 类型不匹配,所以强转为int类型 prt1[-1]==> *(ptr1+(-1))==>*(ptr1-1) int *ptr2 = (int *)((int)a + 1) 此时的a代表的首素地址,地址值是一个常量, 整数+1:相当于跳过一个字节 所以应该画出数组的整体字节布局,注意要考虑小端存放,读取时倒着读取的问题
ptr2是整形指针,解引用向后访问4个字节 所以ptr2指向的是00 00 00 02这四个字节 要倒着拿:所以打印结果为:0 图解:
注意点:整形+1:加一个字节 如:500+1 = 501 整形指针+1:跳过(加)4个字节 四.笔试题4-指针与逗号表达式 坑点:逗号表达式-结果为最后一个表达式的结果 图解:
所以相当于只初始化了前三个素,后面的素未初始化,默认为0 解析:a[0] : 二维数组第一行的数组名,在这里是首素地址,即第一行第一个素的地址p[0] ==>*(p+0)==>*pp是整形指针,解引用向后访问4个字节
五.笔试题5-指针与二维数组 注意:p是数组指针,指向的数组有4个素 指针-指针得到的是二者之间的素个数 p[4] = *(p+4) p[4][2] ==> *(*(p+4)+2) 图解:
&p[4][2]为小地址,&a[4][2]为大地址,小地址减大地址,所以最后结果为-4 -4: 原码: 00000000 00000000 00000100 反码: 补码: 使用%p方式打印:打印的是-4对应的补码 1111 1111 1111 1111 1111 1111 1111 1100 ->结果为:FFFFFFFC 整数在内存中以补码方式存储,打印地址和打印无符号整数一样,都是打印内存中补码 使用%d方式打印:打印二进制补码对应的原码,=> -4 注意:a是二维数组,对应数组指针的类型为:int(*)[5],指向的是有5个素的一维数组 而p是数组指针,指向的数组只有4个素,所以会有警告 ->可以写成 int(*p)[4] = (int(*)[4])a 消除警告 六.笔试题6-指针与二维数组 解析: &aa:取出二维数组的地址 &aa+1:跳过二维数组 &二维数组应该使用数组指针接收,现在保存到整形指针,所以要强转。 aa:没有单独放在sizeof内部,没有&数组名,所以代表的是二维数组首素地址,即二维数组第一行的地址 aa+1:跳过一行*(aa+1) : 相当于拿到了第二行的数组名 等价于 aa[1] 图解:
七.笔试题7-指针与字符指针数组 解析: a是数组,素类型为:char* ,存放的是指向字符串的首字符地址根据后面初始化的内容确定数组的大小char pa = a ; 此处的a是首素地址,char类型——–charpa :一颗*说明pa是指针,另一颗*说明pa指向的类型是char*pa+1:跳过char*所以从字符a的地址向后打印,遇到\0即停止打印打印结果为:at 图解:
八.笔试题9-指针与字符指针数组(难) 这道题比较难,所以我们分表达式解决! 最最最初的内存布局:
解析:++cpp 前置++,cpp先自增,
此时cpp (存放了)指向存放c+2地址的空间(地址) *cpp->得到c+2的地址 cpp得到c+2中存放的内容->首字符P的地址 所以从首字符P开始向后打印,打印结果为:POINT 解析:*–*++cpp+3 注意:上面的表达式,cpp发生自增,指向的已经是存放c+2地址的空间 ++cpp :前置++,cpp发生自增原来是指向存放c+2地址的空间,变为指向存放c+1地址的空间
*++cpp:拿到存放c+1地址的空间,里面存放的是c+1的地址 –*++cpp;前置–,相当于自减解引用cpp之后的内容,即自减c+1的地址,(地址值是常量)。即把原来空间存放的是c+1的地址变成了存放的是c的地址,即现在拿到的是存放c地址的空间
*–*++cpp : 得到c空间中存放的内容(首字符E的地址) *–*++cpp+3 :从首字符E的地址向后+3 ,即为E的地址 从E的地址向后打印->打印结果为ER 解析:*cpp[-2]+3
cpp[-2] ==>*(cpp+(-2) )==> *(cpp-2) *cpp[-2]+3 ==> (cpp-2) )+3 cpp-2:从指向存放c地址空间又变为了指向存放c+3地址的空间
*(cpp-2):得到cpp现在指向的内容,即c+3的地址 (cpp-2):得到c+3空间的内容(首字符F的地址) (cpp-2)+3 :从首字符F的地址向后+3,即为S的地址 从S的地址向后打印,打印结果为:ST 解析:cpp[-1][-1]+1 cpp[-1] ==>*(cpp-1) cpp[-1][-1] ==> *(*(cpp-1)-1) cpp[-1][-1] +1 ==> *(*(cpp-1)-1) +1 注意:此时的cpp指向为第二条表达式之后的状态,上面的第三条表达式并没有改变cpp(即cpp没有自增自减以及被赋值),也没有改变其指向内容,所以第四条表达式的初始状态为计算第二条表达式之后的内存布局
cpp-1:变为指向存放c+2地址的空间
*(cpp-1):得到c+2的地址 *(cpp-1)-1 :c+2的地址值(常量)自减,变成了c+1的地址,即得到了c+1的地址
(*(cpp-1)-1): 得到c+1的内容(首字符N的地址) *(*(cpp-1)-1)+1:得到首字符N向后+1跳过一个字符,即为字符E的地址 从字符E向后打印,打印结果为EW总结: 能坚持看完,你已经比别人优秀很多了!也感谢你看到最后,如果笔者哪里写错了的话,欢迎大佬们评论区指正!如果此文对你有帮助的话,欢迎留个,留个赞再走呀!
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/32836.html