进阶指针(五)—— 指针笔试题

图片来源于网络

✨博客主页:小钱编程成长记
🎈博客专栏:进阶C语言
🎈相关博文:进阶C语言(一)、进阶C语言(二)、进阶C语言(三)、进阶指针(四)

进阶指针(五)—— 指针笔试题

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

笔试题1:

#include <stdio.h>
int main()
{int a[5] = { 1,2,3,4,5 };int* ptr = (int*)(&a + 1);printf("%d,%d", *(a + 1), *(ptr - 1));return 0;
}
//程序的结果是什么?
  1. &a + 1:&a是一个数组的地址,类型是int( * )[5],+1时跳过一个数组的大小。
  2. int* ptr = (int*)(&a + 1);:然后int( * )[5]类型的地址又被强转成了int*类型的地址,赋给ptr。
  3. *(a+1) 是首元素地址+1,然后再解引用。
  4. *(ptr-1) 是ptr-1,然后再解引用。
    在这里插入图片描述
  5. 所以结果是2,5在这里插入图片描述

笔试题2:

//由于还没学习结构体,这里告知结构体的大小是20个字节(在x86(32位)环境下)
#include <stdio.h>struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p的值为0x100000(0x开头的数字是16进制的数字)。如下表达式的值分别为多少?
//已知,结构体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;
}
  1. p+0x1:p是结构体类型的指针,p+0x1跳过一个结构体的大小,结构体Test的大小是20字节,又因为一个地址对应内存中的一字节空间, 地址是以十六进制的形式打印的,所以p+0x1为0x100000+20 == 0x100000+0x16(十进制的20==十六进制的14)

  2. (unsigned long)p+0x1:结构体类型的指针p被强转为unsigned long类型的值,由地址变成了常数,+0x1和+1效果一样。

  3. (unsigned int*)p + 0x1:结构体类型的指针p被强转为unsigned int*类型的指针,+0x1跳一个过unsigned int类型的大小。

  4. %p:是以地址的 形式(地址的长度和进制类型) 打印。
    %x:以十六进制的形式打印
    %#x, "0x%x":以十六进制的形式打印,并显示出十六进制的数据标志。

    在这里插入图片描述

  5. 结果为:0x100014,0x100001,0x100004
    在这里插入图片描述

笔试题3:

#include <stdio.h>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;
}
  1. (int*)(&a+1):一个数组的地址,+1跳过一个数组的大小。最后再将int( * )[4]类型的地址强转为int*类型的地址。

  2. (int*)((int)a+1):首元素地址a被强转为int类型的数据,然后再+1。最后再将int类型的(int)a+1强转为int*类型的地址。

  3. ptr1[-1] == *(ptr1-1)
    在这里插入图片描述

在这里插入图片描述
4. 结果为:4,2000000
在这里插入图片描述

笔试题4:

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

在这里插入图片描述
逗号表达式的结果是最后一个表达式的结果。
在这里插入图片描述
2. 结果为:1
在这里插入图片描述

笔试题5:

#include <stdio.h>
int main()
{int a[5][5];int(*p)[4];//数组指针p = a;//类型不同,不太合适,但非要这样写也行。a-->int(*)[5],  p-->int(*)[4]printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);return 0;
}
  1. p = a:类型不同,不太合适,但非要这样写也行。a–>int( * )[5], p–>int( * )[4]

在这里插入图片描述2. 指针相减的差值的绝对值是指针间元素的个数。
2. %p是打印地址,认为内存中存储的-4的补码就是地址。
3. %d是以十进制的形式打印。
在这里插入图片描述

笔试题6:

#include <stdio.h>
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\n", *(ptr1 - 1), *(ptr2 - 1));return 0;
}
  1. (int*)(&aa+1):aa是二维数组的数组名,&aa+1是跳过一个二维数组的大小。最后int ( * )[2][5]类型的(&aa+1)强转成(int * )类型。

  2. (int*)(*(aa+1))
    第一种理解方式:aa+1是二维数组的首元素地址+1,也就是第一行数组的地址+1,跳过第一行数组的大小。因为aa的类型是int ( * )[5],是一个数组的地址,所以+1后,得到的aa+1的类型也是int ( * )[5],是一个数组的地址, 解引用时访问的空间大小是有5个int类型元素的数组的大小,得到第二行数组,也就是二维数组的第二个元素aa[1],但aa[1]又是第二行的数组名,除了两个例外,aa[1]表示第二行数组的首元素地址。最后被强转为int * 类型的地址。
    在这里插入图片描述
    第二种理解方式:因为 (aa+1) == aa[1] ,并且没有sizeof(),也没有&,所以aa[1]就是第二行数组的首元素地址==&aa[1][0]。最后再强转为int
    类型,因为第二行数组的首元素地址也是int类型的,所以强转前后类型并没有发生变化。

  3. *(ptr1-1), *(ptr2-1):因为ptr1和ptr2都是int*类型的地址,所以-1时跳过一个int类型的大小。

  4. 结果是10,5
    在这里插入图片描述

笔试题7:

//阿里笔试题
#include <stdio.h>
int main()
{char* a[] = { "work","at","alibaba" };char** pa = a;pa++;printf("%s\n", *pa);return 0;
}
  1. char* a[] = {"work","at","alibaba"};字符串作为表达式时结果是首字符地址,所以数组中存放的都是字符串的首字符地址。

  2. char* *pa = a;:a是指针数组的首元素地址,指针数组的首元素是work的首字符地址,所以a是work的首字符地址的地址。用二级指针pa接收。

  3. pa++:因为pa存放的是char * 类型的数据的地址,所以 pa++ 时跳过一个char * 类型的大小。
    在这里插入图片描述

  4. *pa:*pa指向at,是at的首字符地址。

  5. %s:打印字符串,从这个地址开始解引用打印,遇到\0停止(\0不打印)。

  6. 结果是at
    在这里插入图片描述

笔试题8:

#include <stdio.h>
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. char* c[] = {"ENTER","NEW","POINT","FIRST"};:数组c中放的是四个字符串的首字符地址。指针指向字符串,本质上指向的是字符串的首字符

  2. c+3:c是指针数组的首元素地址,也就是ENTER的首字符地址的地址,存放在二级指针中。所以+3是跳过3个ENTER的首字符地址的大小。

  3. char***cpp = cp;:cp是二级指针数组cp的数组名,在这里表示首元素地址,表示c+3的地址。因为c+3的类型是char**,所以要用c+3的地址要存放在三级指针中。
    在这里插入图片描述

  4. cpp前置++或–后,cpp本身也会发生改变

  5. **++cpp:前置++,先++,后使用,跳过1个char * * 类型的大小,然后两次解引用得到char*类型的指针,指向POINT。
    在这里插入图片描述

  6. *--*++cpp+3:cpp先前置++,再 * 解引用,得到char * * 类型的地址c+1。然后前置 --,再 * 解引用,得到char * 类型的地址,最后再跳过3个char类型的大小,指向ENTER中的E。
    在这里插入图片描述

  7. *cpp[-2]+3cpp[-2] == *(cpp - 2),cpp先往后退2个char * * 类型的大小,然后 * 解引用,得到char * * 类型的c+3,再解引用,得到char * 类型的地址。最后跳过3个char类型的大小,指向FIRST中的S。
    在这里插入图片描述

  8. cpp[-1][-1]+1cpp[-1][-1] == * ( * (cpp - 1) - 1),cpp先往后退1个char * * 类型的大小,再 * 解引用,得到char * * 类型的c+2。然后后退1个char * 类型的大小,在解引用,得到char*类型的地址。最后跳过1个char类型的大小,指向NEW中的E。
    在这里插入图片描述

  9. %s:打印字符串,从这个地址开始解引用打印,遇到\0停止(\0不打印)。
    在这里插入图片描述

总结

这篇文章我们通过做一些指针笔试题更加深入的理解了指针。
大家有什么问题可以在评论区多多交流,如果文章有错误的地方,欢迎在评论区指正。感谢大家的阅读!大家一起进步!

点赞收藏加关注,C语言学习不迷路!
图片来源于网络

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/128365.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【arm实验1】GPIO实验-LED灯的流水亮灭

linuxlinux:~/study/01-asm$ cat asm-led.S .text .global _start _start: 1.设置GPIOE寄存器的时钟使能 RCC_MP_AHB4ENSETR[4]->1 0x50000a28 LDR R0,0X50000A28 LDR R1,[R0] 从r0为起始地址的4字节数据取出放在R1 ORR R1,R1,#(0x1<<4) 第4位设置为1 ORR R…

想要精通算法和SQL的成长之路 - 存在重复元素

想要精通算法和SQL的成长之路 - 存在重复元素 前言一. 存在重复元素II二. 存在重复元素III2.1 基于红黑树增删改查 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 存在重复元素II 原题链接 思路&#xff1a; 我们用HashSet存储元素&#xff0c;做到去重的效果。同时存储…

黑豹程序员-架构师学习路线图-百科:Database数据库

文章目录 1、什么是Database2、发展历史3、数据库排行网4、总结 1、什么是Database 当今世界是一个充满着数据的互联网世界&#xff0c;各处都充斥着大量的数据。即这个互联网世界就是数据世界。 支撑这个数据世界的基石就是数据库&#xff0c;数据库也可以称为数据的仓库。 …

基于Kylin的数据统计分析平台架构设计与实现

目录 1 前言 2 关键模块 2.1 数据仓库的搭建 2.2 ETL 2.3 Kylin数据分析系统 2.4 数据可视化系统 2.5 报表模块 3 最终成果 4 遇到问题 1 前言 这是在TP-LINK公司云平台部门做的一个项目&#xff0c;总体包括云上数据统计平台的架构设计和组件开发&#xff0c;在此只做…

【云笔记篇】Microsoft OneNote笔记插件推荐OneMore

【云笔记篇】Microsoft OneNote笔记插件推荐OneMore OneMore插件是一款非常强大&#xff0c;多达一百多个扩展功能的OneNote笔记插件&#xff0c;而且免费开源&#xff0c;不断更新的优秀插件—【蘇小沐】 1、实验 【OneMore官网&#xff1a;OneMore - a OneNote add-in (on…

Unity Golang教程-Shader编写一个流动的云效果

创建目录 一个友好的项目&#xff0c;项目目录结构是很重要的。我们先导入一个登录界面模型资源。 我们先创建Art表示是美术类的资源&#xff0c;资源是模型创建Model文件夹&#xff0c;由于是在登录界面所以创建Login文件夹&#xff0c;下面依次是模型对应的资源&#xff0c…

分享几个通用个人简历模板|行业通用

Home(https://cvjury.com/) 专业设计的简历模板。 在竞争激烈的就业市场中脱颖而出的有效策略。 侧重于向招聘人员传达独特的价值主张。 帮助创建引人注目的简历、求职信和LinkedIn资料。 面向毕业生和学生的个性化简历解决方案。 添加图片注释&#xff0c;不超过 140 字&…

计算机视觉: 基于隐式BRDF自编码器的文生三维技术

论文链接: MATLABER: Material-Aware Text-to-3D via LAtent BRDF auto-EncodeR 背景 得益扩散模型和大量的text - image 成对的图片&#xff0c; 现在文生2D的模型已经比较成熟的框架和模型&#xff0c;主流的技术比如说stable diffusion 和 midjourney 以及工业领域runway 等…

基于MFC和OpenCV实现人脸识别

基于MFC和OpenCV实现人脸识别 文章目录 基于MFC和OpenCV实现人脸识别0. 项目说明1. 创建项目2. 启动窗口3. 登录窗口-添加窗口、从启动窗口跳转4. 启动窗口-美化按钮5. 登录窗口-美化按钮、雪花视频6. 注册窗口-美化按钮、雪花视频、从启动窗口跳转7. 注册窗口-开启摄像头8. 注…

geecg-uniapp 源码下载运行 修改端口号 修改tabBar 修改展示数据

APP体验&#xff1a; http://jeecg.com/appIndex技术官网&#xff1a; http://www.jeecg.com安装文档&#xff1a; 快速开始 JeecgBoot 开发文档 看云视频教程&#xff1a; 零基础入门视频官方支持&#xff1a; http://jeecg.com/doc/help 一&#xff0c;下载安装 源码下载…

Linux防火墙之--SNAT和DNAT

1.SNAT是什么 SNAT又称源地址转换。源地址转换是内网地址向外访问时&#xff0c;发起访问的内网ip地址转换为指定的ip地址&#xff08;可指定具体的服务以及相应的端口或端口范围&#xff09;&#xff0c;这可以使内网中使用保留ip地址的主机访问外部网络&#xff0c;即内网的多…

基于SpringBoot的靓车汽车销售网站

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 车辆展示管理 车辆品牌管理 用户交流管理 购物车 用户交流 我的订单管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的…