一篇文章让你搞懂指针笔试题(加深对指针的理解)

news2024/9/23 3:21:25

在这里插入图片描述

指针笔试题

笔试题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;
}

给定一个数组a,当我们取地址a的时候,我取出的是整个数组的地址,我取地址a+1就指向了数组最后一个元素的后一个位置,这时候我们将&a强制类型转化为int*,因为&a的指针类型本质上应该是int(*)[5],加1之后指针类型不变,当我强制类型转化之后赋给ptr,ptr就指向了元素5后面那个位置,ptr-1向前减1就指向了元素5这个地址,解引用就得到了5,第一个%d理所当然很好理解就是2

笔试题2

#include<stdio.h>
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设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;
}

这里我们直接将0x100000这个值赋给p,同时需要将0x100000强制类型转化为结构体指针(struct Test*)
1:p+0x1—+1要跳过一个结构体(20个字节)—需要转化为十六进制数—所以为0x100014
2:当我们将p强制类型转化为uhnsigned long的时候,就回归到了我们普通的数值的计算上来,也就是0x100000+1—>0x1000001
3:p强制类型转化为unsigned int*的时候,这里的+1要跳过字节,所以应该为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;
}

这里设计大小端的知识
我们当前的机器是小端,所以按照小端存储的方式来存储
此时的&a在01的位置
&a+1跳过整个数组就指向了00的后一部分
所以ptr1也就指向了00的后一部分
所以ptr1[-1]==(ptr1-1)
ptr1[-1]向前跳了一个整型也就走到了前面的00的最后一个位置
接下来看ptr2//
a是首元素的地址,a的指针类型本身应该是Int
的,我将他强制类型转化为整型,整型加1就得到了下一个字节,这个可以类比笔试题2的知识,有异曲同之妙
所以此时ptr2就指向了01后面的00的位置了
所以这个时候我要从00这个位置开始向后面访问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;
}

这里的二维数组的表示不同于我们平时的二维数组的表示方式,这里的二维数组的内容是由括号加逗号构成的,逗号表达式我们只取逗号后面的那个数,所以我们取出1,3,5三个数组依次排序,其他位补0即可
所以我们得到1这个答案
这里的p不是野指针,因为我在定义了这个指针类型之后立马给大传了低第一行数组名首元素的地址给他

笔试题5

#include<stdio.h>
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;
}

后面会有图片演示,现在我给大家文字叙述
数组名的类型为int()[5],p的类型为int()[4],将数组名赋给p
p最终指向的是a的首元素的地址,p向后走一步是要跳过4个整型的
看图
在这里插入图片描述
随着数组下标的增长,地址是由低到高变化的
指针减去指针得到的是指针与指针之间的元素个数
所以我们%d打印的是-4,-4在内存中是以补码的形式存储的
那么%p怎么处理呢?

//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]);//-4
//	//10000000000000000000000000000100
//	//11111111111111111111111111111011
//	//1111 1111 1111 1111 1111 1111 1111 1100
//	//F    F    F    F    F    F    F    C
//	//0xFFFFFFFC
//
//	return 0;
//}
//

%d是以原码的形式打印有符号的整数
内存中存储的是补码
-4以%p打印的时候不存在有无符号之分
他就将1111 1111 1111 1111 1111 1111 1111 1100当作十六进制的地址打印就可以了,老铁们可以拷贝代码去进行验证

笔试题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", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

首先这是一个二维数组
&aa的指针类型为int(*)[5]

ptr1指向的是元素10后一个位置
所以需要强制类型转化为int*
ptr1-1就得到了元素10处的地址,再解引用就得到10这个元素
对于ptr2指向了第二行数组的首元素地址
数组名相当于首元素的地址
所以这里得到的是元素6处的地址
所以ptr2-1再解引用就得到地址5处的元素值5

笔试题7

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

这是一个字符指针,a数组名首元素的地址,将一级指针首元素的地址用一个二级指针来接收。pa就指向work这个元素
pa++就指向at这个元素的地址,然后解引用就得到了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;
}

我们对比着下图来讲
在这里插入图片描述
cpp存放的是cp首元素的地址,cpp先前置++,当我在前置++完过后我就指向了C+2的位置了,执行完前置++之后就要执行*号了//
第一个星号先解引用得到了cp里面第二个元素地址的值,而C+2是指向"POINT"处的地址,此时我再次解引用操作就得到了”POINT“这个元素

我们此时有再一次讲CPP++了一次,这是CPP就指向了C+1,先解引用得到C+1这个值,然后再次–就得到了C这个值,C指向的是"ENTER"这个元素,然后加3向后移三位得到ER,%s打印到\0结束,所以我打印出来的是ER
值得注意的是这里的CPP是随时在发生变化的

我们接着走
CPP[-2]=CPP-2在解引用就得到了CP+2这个位置的值,CP+2指向的又是”FIRST“这个元素的地址,我再次进行一次解引用就得到了"FIRST"这个值,然后首元素加3就得到了S这个元素,再次%s打印字符串到\0结束,所以打印出来ST

最后一个
想象成一个二维数组最后一个打印可以写成下面代码

*(*(cpp - 1) - 1) + 1;

同理,C+1指向元素”NEW“,元素N加1得到E,%s打印到\0结束就得到了EW
这道题的图解,图有点乱,但文字叙述给大家叙述清楚了的
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于stm32单片机的智能门禁系统设计

一.硬件方案 基于stm32单片机的智能门禁系统设计的整体电路主要由采用STM32F103单片机&#xff0c;4*4矩阵按键电路&#xff0c;电子锁继电器驱动电路&#xff0c;开锁LED指示灯&#xff0c;LCD1602显示屏电路&#xff0c;蜂鸣器报警电路&#xff0c;RFID感应电路&#xff0c;…

如何查看 当前安装的vue版本

目录 1 实现 1 实现 要查看当前安装的 Vue 版本&#xff0c;可以使用以下方法&#xff1a; 在终端或命令提示符中运行以下命令&#xff1a; vue --version如果你使用的是 Vue CLI 创建的项目&#xff0c;可以在项目的根目录中找到 package.json 文件。在该文件中&#xff0c…

【CSS】悬浮动画

文章目录 效果展示代码实现 效果展示 代码实现 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>一颗不甘坠落的流星</title></head><style type"text/css">.bth {/* 添加背景颜色 */backgr…

2023-7-7-第十三式模板方法模式

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

代码随想录算法训练营第60天/最后一天 | 84.柱状图中最大的矩形

今日任务 目录 84.柱状图中最大的矩形 - Hard 84.柱状图中最大的矩形 - Hard 题目链接&#xff1a;力扣-84. 柱状图中最大的矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够…

Android之Handler分析与理解

Android中的Handler是一个用于处理消息和线程间通信的机制。它可以将Runnable对象或Message对象发送到特定的线程中进行处理。 使用Handler的主要目的是在不同的线程之间进行通信&#xff0c;特别是在后台线程中执行一些任务后&#xff0c;将结果发送到UI线程进行更新。 流程图…

pearsonr 报错:numpy.float64 can not be interpreted as an integer

【1】 模型求出pred&#xff0c;pearsonr(pred,true&#xff09; 出现以下报错&#xff1a; 【2】解释&#xff1a; 当在计算皮尔逊相关系数&#xff08;Pearson correlation coefficient&#xff09;时出现"numpy.float64 can not be interpreted as an integer"的…

7.7~7.8学习总结

StringBuider&#xff1a;线程不安全&#xff0c;效率高 StringBuffer&#xff1a;线程安全&#xff0c;效率低&#xff1b; 用法举例&#xff1a; class TWC {public static void main(String []args){StringBuilder sbnew StringBuilder("小麻子爱吃粑粑");Syst…

C语言学习(三十六)---文件操作

上节内容中&#xff0c;我们学习了练习了动态内存的练习题&#xff0c;并且学习了柔性数组的相关内容&#xff0c;大叫要好好掌握&#xff0c;今天&#xff0c;我们将学习文件操作的相关内容&#xff0c;这部分内容实际上很多&#xff0c;我们以点代面&#xff0c;好了&#xf…

windows已有mysql的情况下 mysql8 安装

安装前先停掉本地已有的mysql服务https://dev.mysql.com/downloads/mysql/ 下载mysql压缩包解压创建 my.init 文件 [mysqld] port 3307 basedirF:\mysql-8.0.33-winx64\mysql-8.0.33-winx64 datadirF:\mysql-8.0.33-winx64\mysql-8.0.33-winx64\data max_connections200 cha…

3.3.内存的学习,pinnedmemory,内存效率问题

目录 前言1. Memory总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习精简 CUDA 教程-内存模型&#xff0c;pinned memory&am…

2023.7.08

#include "widget.h"void Widget::my_slot() {if((edit1->text()"admin")&&(edit2->text()"123456")){qDebug()<<"登陆成功";emit jump();close();}else{qDebug()<<"登陆失败";} }void Widget::b…

OSPFv2基础02_工作原理

目录 1.OSPF接口状态 2.OSPF邻居状态 2.1 OSPF邻居状态类型 2.2 广播网络OSPF邻接关系建立 3.Router ID&#xff08;路由器ID&#xff09;选举 4.DR和BDR选举 4.1 为什么引入DR和BDR&#xff1f; 4.2 DR和BDR的作用 4.3 DR和BDR选举过程 4.4 DR和BDR选举原则 5.OSPF路…

基于单片机指纹考勤系统的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;利用指纹采集模块存储打卡信息&#xff1b;12864显示当前考勤信息&#xff0c;时间 &#xff1b;如果迟到 语音播报 您已迟到&#xff1b;按键进行注册指纹、删除指纹、设置当前时间和签到时间、查询打卡等&#xff1b;具有掉电保存…

【YOLOv7调整detect.py】1.调整检测框粗细,2.设定标签颜色,3.只显示与标签数目相同的检测结果

目录 1. 调整检测框粗细2. 设定标签颜色3. 只显示与标签数目相同的检测结果 1. 调整检测框粗细 在detect.py中按住CtrlF检索line_thickness定位过去&#xff0c;在129行左右&#xff0c;更改line_thickness的大小即可&#xff0c;例如改为line_thickness3 2. 设定标签颜色 在…

Spring核心 and 创建使用

Spring核心 and 创建使用 文章目录 Spring核心 and 创建使用一、Spring的定义1.1什么是IoC1.1.1 理解控制反转&#xff08;IoC&#xff09;1.1.2 控制反转式程序开发 1.2 使用Spring IoC核心功能2.1 DI的概念说明 二、Spring的创建和使用2.1 创建一个Maven项目2.2 添加Spring框…

解决在jupyter notebook中找不到pip安装后的库

解决在jupyter notebook中找不到已安装的库

Todo-List案例版本二

(160条消息) Todo-List案例版本一_bubbleJessica的博客-CSDN博客 引入了localStorage&#xff0c;让案例更加完善 src/App.vue <template><div id"root"><div class"todo-container"><div class"todo-wrap"><MyHe…

pycharm 打开终端,安装第三方程序

鼠标移动到左下角 弹出列表&#xff0c;选择终端&#xff0c;当然也可以用快捷键唤出&#xff0c; 可以输入命令进行第三方库的安装

Redis实战案例14-分布式锁的基本原理、不同实现方法对比以及基于Redis进行实现思路

1. 分布式锁基本原理 基于数据库的分布式锁&#xff1a;这种方式使用数据库的特性来实现分布式锁。具体流程如下&#xff1a; 获取锁&#xff1a;当一个节点需要获得锁时&#xff0c;它尝试在数据库中插入一个特定的唯一键值&#xff08;如唯一约束的主键&#xff09;&#xff…