每一个不曾起舞的日子,都是对生命的辜负。

八道笔试题解析

  • 题目:
    • 笔试题1
    • 笔试题2
    • 笔试题3
    • 笔试题4
    • 笔试题5
    • 笔试题6
    • 笔试题7
    • 笔试题8
  • 总结:

题目:

笔试题1

int main()
{int a[5] = { 1,2,3,4,5 };int* ptr = (int*)(&a + 1);printf("%d,%d", *(a + 1), *(ptr - 1));//2 5return 0;
}
//程序的结果是什么?

a表示这个数组的首地址,&a则是整个数组的地址,故在进行(&a+1)操作的过程中,+1操作跳过了a整个数组,由于a是数组,&a代表数组指针,在赋值ptr的过程,左面是整形指针,右面是数组指针,两边类型有所差异,故用(int*)将(&a+1)强转成整形指针类型,否则会产生警告。故对于*(a+1),a+1为2的地址,(a+1)就是2,ptr-1为5的地址,(ptr-1)就是5。

笔试题2

struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p;//即p = (struct Test*)0x100000
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

0x表示16进制,0x1代表1,由于p是指针类型,指针+1或者减1代表跳过这个类型的大小,即:
(1)一个整形指针+1代表跳过一个整型
(2)一个结构体指针+1代表跳过一个结构体
(3)一个字符指针+1代表跳过一个字符
(单位:字节)
故p+0x1代表跳过这个结构体(20字节),化成16进制就是14,故p+0x1 为0x100014;(unsigned int)p代表普通整形类型,故+1就代表这个整形数字+1,并不是地址之间的运算,(unsigned int)p+0x1 为0x100001;(unsigned int*)p把结构体类型指针强转成无符号整型的指针,故+1所跳过的步长从20变成了4,即(unsigned int*)p+0x1为0x100004。

笔试题3

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;
}

对于ptr1的操作与笔试题1操作相同,ptr1[-1]表示*(ptr1-1),即为4;
对于ptr2的操作,假设a的地址为0x0012ff40,当强转成int类型时,即表示整数0x0012ff40故(int)a+1就代表数字0x0012ff41,再强转成(int*)类型,又变成了地址,即在a原来的地址上向右移动了一个字节大小,故ptr2指向位置如图所示,由于是int*,故解引用时需从ptr2指向的位置开始数直到第四个字节00 00 00 02,,由于是小端存储模式(上篇提到过),故读数需从高地址然后低地址,02 00 00 00,由于地址本是16进制,%x打印即为20000000

笔试题4

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

在此之前,我们需要注意的是逗号表达式的结果为最后面的数字,即a[3][2]的内部数字为:{
1,3,
5,0,
0,0}
a[0],表示矩阵第一行的数组名,故p代表第一行数组名,p[0] = a[0][0] = 1;

笔试题5

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;
}

由以上代码我们看到,a为int [5[[5],p为int(*)[4],由于类型不匹配,故赋值时会发生警告,但仍然可以运行,通过绘图,我们可以看出p[4][2]与a[4][2]的具体位置,地址-地址等于地址之间相差元素的个数,故以%d形式打印时结果为-4;当以%p打印时,根据-4的原码:10000000000000000000000000000100,
求出反码:111111111111111111111111111111111011,再求出补码:111111111111111111111111111111111100,可化为ff ff ff fc

笔试题6

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;
}

经过几道题的讲解,这道题与前几道类似,主要就是将图化成一行,而不是两行,故得到的结果为10 5

笔试题7

int main()
{char* a[] = { "work","at","alibaba" };char** pa = a;pa++;printf("%s\n", *pa);return 0;
}

数组名表示首元素地址,当把a赋值给pa时,pa指向了a的地址,由于pa为char**即pa++移动的大小为一个char*大小,故表示如图,pa指向(a+1),*pa代表:
*(a+1)即a[1],即以%s打印a[1],结果为at。

笔试题8

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;
}

作为最后一题出现,势必会很麻烦,因此,我们需要弄清它们之间的关系,即前三行代码之间的关联,如上图。
1)当我们执行第一个printf时,++cpp,则cpp指向了cp[1],即:

故**cpp就是将连线的一点一点解引用,*cpp找到cp[1],
**cpp找到c[2],最终打印POINT;
2)当我们执行第二个printf时,又++cpp,指向cp[2],再解引用,即通过连线找到下一级,即到达cp[2],–cp[2],即cp[2]从指向c[1]变成指向c[0],再解引用,到达ENTER的首地址,再+3,到达ER,即:
3)当我们执行第三个printf时,可变成:

即cpp-2为cp[0]的地址,解引用变成cp[0],再解引用为c[3],c[3]看成数组名,为FIRST首元素F的地址,+3为S的地址,故结果为ST;

4)当我们执行第四个printf时,按照上述找线段的方法,不难找到:
即结果为EW。

总结:

通过以上八道题的训练,囊括了指针核心的运算以及最难理解的部分,不难看出,画图并且画好图才是降伏一切指针关系的最终手段。

【指针训练——八道题】相关推荐

  1. C语言-八道题深入理解c指针

    八道题深入理解c指针 1. 第一题 程序运行结果是什么? int main() {int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1) ...

  2. 指针应用——八大笔试题详解

    目录 前言 正文 第一题 第二题 第三题 第四题 第五题 第六题 第七题 第八题 总结 鸣谢 前言 我们在前面学习了指针初阶.进阶的知识,作为C语言中的重难点,指针有很大的几率出现在面试时的笔试题中, ...

  3. 2021年春季学期-信号与系统-第三次作业参考答案-第八道题

    本文是 2021年春季学期-信号与系统-第三次作业参考答案 中的参考答案. ▌第八道题 8. 某LTI系统,输入信号e(t)=2e−3tu(t)e\left( t \right) = 2e^{ - 3 ...

  4. C语言编程课后训练,C语言编程课后训练20道题.doc

    C语言编程课后训练20道题 C语言编程课后训练20道题/*-------------------------------------------------------[程序填空]---------- ...

  5. 寒假训练八(优先队列)2020.02.14(7题)

    寒假训练八(优先队列)id:530 Problem:A 买饭-优先队列 Description 林大食堂非常拥挤,得排队买饭,陈老师也是一样的! 有n个人在一个卖饭窗口前排队买饭,假如每个人买饭的时间 ...

  6. 新手Web前八道题训练

    看到这个以后,我们可以使用Ctrl+u来查看网页源代码,可以在里面找到flag 第二题 我们发现我们只能输入一位数,那么我们可以使用Ctrl+Shift+i来进行源代码的更改 我们发现这里规定了最大字 ...

  7. 【C】牛客网 编程入门训练138道题

    刷题 传送门:编程入门训练 实践出真知 #include <stdio.h>int main () {printf ("Practice makes perfect!" ...

  8. 指针进阶·八道笔试题(四)

    目录 指针笔试题 001 解析 002 解析 003 解析 004 解析 005 解析 006 解析 007 解析 008 解析 结束语 指针笔试题 001 //001 int main() {int ...

  9. “蓝桥杯”软件大赛入门训练4道题

    问题描述 Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1. 当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少. 输入格式 输入包含一个整数n ...

最新文章

  1. 修改oracle+sga+size,oracle自动内存共享管理测试。修改 oracle 11g SGA_MAX_SIZE。
  2. PHP框架编写和应用知识点,写PHP框架需要具备那些知识?
  3. java拼接sql保留两位小数_SQL 保留两位小数的实现方式
  4. java从静态代理到动态代理的理解
  5. 2017/Province_Java_B/3/承压计算
  6. 面试官最常问的垃圾回收器CMS
  7. 【服务端渲染】手动部署 NuxtJs 项目
  8. 基于JAVA+SpringMVC+Mybatis+MYSQL的图书馆预约占座管理系统
  9. 算法2(二分查找法)
  10. kafka内部消费偏移
  11. blob字段如何更新_Axure RP8 中继器:字段增删改
  12. 翻译:生产中的机器学习:为什么你应该关心数据和概念漂移
  13. 倍福嵌入式控制器PLC各型号介绍
  14. 学生成绩管理系统c语言直方图,Excel表格的25招必学秘技 电子表格常用技巧大全...
  15. 路飞学城Python-Day78
  16. 计算机专业师范类分析,师范生应具备的信息技术能力分析
  17. 2016 CSDN最佳博客(Android)
  18. 腾讯bugly接入详解
  19. 5款服装进销存软件测评,教您如何挑选出好用的
  20. 域名申请需要多长时间?域名申请后多久能使用?

热门文章

  1. PMP 80个输入输出总结
  2. 前端 给确定按钮加一个确认提示
  3. vue打包之后谷歌浏览器可以正常打开,而其它一些浏览器360等无法正常打开
  4. Linux和Win10双系统出现GUN GRUB解决方法
  5. mysql dml语句 先读取在更新_事务的4个特性——ACID(原子性、一致性、隔离性和持久性)、更新丢失问题...
  6. NC开发笔记——NC63开发方法总结
  7. 《深入理解计算机系统》(CSAPP)实验七 —— Malloc Lab
  8. 编写一个函数判断一个整数是不是素数c语言,编写函数判断一个整数是否为素数...
  9. 下列关于python语言中缩进的说法正确的是_关于Python程序中与“缩进”有关的说法中,以下选项中正确的是 _________ 。_学小易找答案...
  10. Vue中 前端实现生成 PDF 并下载