【C进阶】指针笔试题汇总

⭐博客主页:️CS semi主页
⭐欢迎关注:点赞收藏+留言
⭐系列专栏:C语言进阶
⭐代码仓库:C Advanced
家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们的支持是我创作最大的动力,欢迎友友们私信提问,家人们不要忘记点赞收藏+关注哦!!!


前言

指针的笔试题有许多,这都是C语言基础时候的笔试题,下面有8道笔试的题目,是很精炼的几道笔试题,主要分为三个模块,题目,答案及解析和代码,这里放上代码是为了供大家去进行复制粘贴到编译器里面试一试,在完成这些题目的时候需要细心与耐心,慢慢来,结合前面的知识图谱进行解读,这需要的是前面很好的指针基础以及了解前面的知识,但大家放心,我会仔仔细细,慢慢讲解这些题目,让大家完全了解和掌握。


一、题1

(一)题目

在这里插入图片描述

(二)答案及解析

答案:2,5
解析:大家看图,&a拿到的是整个数组的地址,也就是拿到蓝色方框的地址,&a的类型是int(*)[5],是个数组指针,+1这个操作是跳过整个数组跳到下一个数组,而这串数组是存放在cpu里面的,前后都不知道存放的是什么,只有a这个数组是被维护的。题目中的ptr又要是个(int*)的指针类型,那就需要将&a的类型进行强制类型转换成int*,所以题目问的是*(ptr-1),那不就是这个a数组的末尾元素吗,那就是5了,至于*(a+1)那就更简单了,a为首元素的地址,+1就是第二个元素的地址,一解引用那就直接为2。

在这里插入图片描述

(三)代码

int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}

二、题2

(一)题目

在这里插入图片描述

(二)答案及解析

答案:0x00100014 0x00100001 0x00100004(0x表示十六进制)
解析:此题考察的就是指针+1,大家看图,我们规定p的值就是0x100000。
第一个printf是指针+1,跳过的是一整个结构体的大小,因为上面定义了*p就是用Text结构体定义的,那就是struct Text *p;所以+1跳过了一整个结构体,这个结构体的大小是20个字节,那我们跳过20个字节,在十六进制中是“14”,而我们是在32位机器下运行的,那这个类型是4个字节,前面补0,所以第一个答案是0x00100014。
第二个printf是将结构体指针p转化为无符号整型的p,整型+1的结果就是在原本的值的基础上+1,所以就是0x00100001。
第三个printf是将结构体指针p转换成为无符号整型指针,既然是指针,跳过的就是整型指针类型,那就是跳过4个字节,答案就是0x00100004。
在这里插入图片描述

ps:%p打印的是地址,32位机器上是占4个字节的,也就是0x00 00 00 00八位。

(三)代码

//假设这个Text结构体的大小是20个字节
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000
int main()
{
	p = (struct Test*)0x100000;
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

三、题3

(一)题目

在这里插入图片描述

(二)答案及解析

答案:0x4 0x2000000(0x表示十六进制)
解析:大家看图。我们先分析ptr1指针,&a是取出的一整个数组的地址,而+1以后是跳过这一整个数组往后找下一个数组,那后面打印的是ptr[-1]相当于ptr1-1,ptr1-1是往后一个整型指针类型的大小,那么指向的就是4,那么答案就是4。
再分析一下ptr2,这时候我们需要展开所有字节来看了,这就是指针的魅力所在,我们发现a应该是首元素的地址,但解引用成(int),所以a就是一个简单的整型,不是指针,所以单纯的+1就是单纯的跳过一个字节,因为4+1=5(跳过的是1个字节),指针4+1=8(跳过的是4个字节),那所以(int)a+1指向的就是00这个字节,而当(int)a+1整个强制类型转换成为(int*),整型指针占4个字节,那就是从(int)a+1这个指向的字节位置往后找4个字节即可,那就是00 00 00 02,而我们题目给定的条件是小端存放,且在x86的情况下,那么我们进行拿出来显示的时候是02000000,所以%p结果就是0x02000000,而这道题目要求的是%x,也就是十六进制,则前导的0要删掉。
在这里插入图片描述

ps:%x表示的是十六进制,前导的0都需要删掉。

(三)代码

//小端,X86环境
int main()
{
	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1);
	int* ptr2 = (int*)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);
	return 0;
}

四、题4

(一)题目

在这里插入图片描述

(二)答案及解析

答案:1
解析:这道题目是在是太贼了,这花括号里面不是花括号,而是逗号,我思考了半天这道题,死来想去应该是0,而答案却是1,原来是有个(,),逗号表达式返回的是后面的值,所以值为1,3,5,0,0,0。我们知道二维数组的值那就好办了,a[0]就是二维数组的首行数组名,那也就是p这个指针指向的是a这个二维数组首行的地址,也就是两个元素,而p[0]又是*(p+0)==*p,那也就是1了。

在这里插入图片描述
在这里插入图片描述

(三)代码

#include <stdio.h>
int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);
	return 0;
}

五、题5

(一)题目

在这里插入图片描述

(二)答案及解析

答案:0xFFFFFFFC -4
解析:这道题目坑是真的多呀,我们先看二维数组a的类型,是int(*)[5]是一组中有五个元素的,而p的类型是int(*)[4],是一组中有4个元素的,这两个类型都不匹配,还不强制类型转换,直接即将a赋给p了,这让p太为难了,p说没事儿,我接收你,那好,p现在是将a的内存空间进行划分,四个元素四个元素划分一个,所以我们要求的p[4][2]就是褐色那片区域,而指针指向的是褐色所在的那片区域的最左边,而我们要求的a[4][2]就是绿色区域了,根据指针相减,发现是低地址减高地址,那就是-4了,可是此题没完,前面要的是%p,那是个地址,我们知道在计算机内存中数字是以二进制的补码存储的,那这就很简单了,地址又不看补码的,直接换算成地址,那就是0xFFFFFFFC了。
在这里插入图片描述

(三)代码

int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	return 0;
}

六、题6

(一)题目

在这里插入图片描述

(二)答案及解析

答案:10 5

解析:如下图所示,我们先知道的是&aa取的是整个数组的地址,那+1是跳过整个二维数组,那就是指向10的末尾,那-1是指向的是10,再解引用就拿出来的结果为10,而aa是首个数组的地址,+1是跳过首个数组到第二个数组的头,但此时也是取的是第二个数组,但是进行强制类型转换了,所以ptr2指针-1是跳过一个元素,所以显示的是5。

在这里插入图片描述

(三)代码

int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

七、题7

(一)题目

在这里插入图片描述

(二)答案及解析

答案:at
解析:我们先看字符指针数组char* a[],这个指针指向的是后面三个字符串的首元素,而char** pa=a,所以pa指向的是字符指针a的首元素,这个关系我们清楚了以后,看一看pa++的含义,我们此时想了,char** pa的含义是:char* *pa,这个意思是对pa进行加一的操作,是跳过的一个char*元素,所以指向的是’a’,进行解引用打印字符串打印的就是at。
在这里插入图片描述

(三)代码

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

八、题8

(一)题目

在这里插入图片描述

(二)答案及解析

答案:POINT ER ST EW
解析:总的分析:
在这里插入图片描述
分开单独分析:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(三)代码

int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}

总结

终于归纳完这些练习题了,这些练习题实在是太坑了,那么多的坑等着你去踩,但是我们需要一步步去了解一下它们,它们也不是那么难以理解与制作,那就需要有学习的方法,利用画图或者是反推是非常重要的,所以对于我们来说,我们需要把这些题目当成朋友去看待,相信总能解决的,感谢大家耐心阅读!!!


客官,码字不易,来个三连支持一下吧!!!

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2022horse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值