【C语言】初识指针(终篇)

news2024/11/16 15:49:47

摸了一手秀发,发现还在~


目录

1、指针运算

1.1指针加减整数

1.2指针减指针

1.3指针关系运算

2、二级指针

3、指针和数组

4、指针数组


前言:

大家好,我是拳击哥。上一期我们讲到了指针类型,指针的访问步长,野指针概念。那今天我们就来讲点新的东西,东西不多就四个模块:指针运算、二级指针、指针和数组、指针数组。下面我就来介绍它们的用法。

初识指针(一)

初识指针(二)


1、指针运算

指针运算分为三种情况:

  • 指针加减整数
  • 指针减指针
  • 指针的关系运算

1.1指针加减整数

指针加减整数是什么意思呢,就是指针在往前加往后减造成一段数据发生改变。这就是指针加减的意义,它能使数据发生改变。我们拿加法来举例:

#include<stdio.h>

#define N_VALUES 5

int main()
{
	float values[N_VALUES] = { 1.2f,2.2f,3.2f,4.2f,5.2f };
	float* p;
	for (p = &values[0]; p < &values[N_VALUES];)
	{
		*p++ = 0;
	}
	for (int i = 0; i < N_VALUES; i++)
	{
		printf("%.0f ", values[i]);
	}
	return 0;
}

输出结果: 0 0 0 0 0

上述程序我依次来给大家讲解:首先初始化了一个单精度浮点型数组values有5个元素,并且定义了单精度浮点型指针变量p。大家不要认为这个程序很复杂,就是define定义了一个常量我把这个常量写得比较有逼格一点。大家容我细细道来。

第一个for循环()里面,让指针p指向values第一个元素的地址,并且p指向的地址<values最后一个元素的地址+1。这样造成什么呢,造成循环5次。

我们再看循环体内,第一次循环*p++=0,先对p解引用也就是先修改values第一个元素为0后再使p++也就是使p指向地址往前增长1。所以此时p指向的是values数组第二个元素的地址。直到最后p指向的地址超出了values数组最后一个数组元素地址,结束循环。

第二个for循环就是遍历values数组,依次打印被修改后的values的各个元素值。

相信大家对指针加法有了不一样的见解,指针加一就是使指针指向的地址往后增一。因此我可以先解引用当前地址并且修改当前地址值,或者再往后加一等等,可以实现各种您想要的结果。您学会了吗?


1.2指针减指针

理解了指针加法,减法也就不难理解了,也就是指针指向的地址往前减一,因此我可以得到上一个元素的地址

1.3指针关系运算

指针关系运算是什么意思呢,就是比较两个指针之间的大小。两个指针的大小又用什么衡量呢,用指针指向的地址的大小来衡量。因此我们就不难理解指针关系运算是怎么回事了。

#include<stdio.h>

int main()
{
	int arry[3] = { 1,2,3 };
	int* p1=arry;
	int* p2=arry+1;
	if (p1 > p2)
	{
		*p1 = 0;
	}
	else
	{
		*p2 = 0;
	}
	for (int i = 0; i < 3; i++)
	{
		printf("%d ", arry[i]);
	}
}

输出结果:1 0 3 

上述程序很明显定义了p1指向arry数组的首地址,p2指向了arry数组的第二元素地址。因此p1<p2执行了*p2=0。这就是指针的关系运算,判断两个指针指向地址的大小从而进行一些操作。希望大家能够理解。


2、二级指针

平常我们定义的指针是一级指针如:int* p=NULL;只有一个*号这就是一个一级指针。那么二级指针就是有两个*号的指针如:int** pp=NULL;二级指针怎么用呢,有一代码:

#include<stdio.h>

int main()
{
	int a = 10;
	int* p = &a;
	int** pp = &p;
	**pp = 20;
	printf("%d\n", a);
	return 0;
}

输出结果:20 

上述代码,我来拆分讲解。首先我先定义了一个整型变量a=10、一个一级指针变量p指向a的地址和一个二级指针变量pp指向指针变量p的地址

指针p存放的是a的地址,二级指针pp存放的是指针p的地址。然后对pp进行双解引用并把20赋值给双解引用后的pp,从而修改了a的值。结合下图来理解:

以上地址都是随机的,首先变量a里面存的是10,指针p里面存的是a的地址二级指针pp里面存的是指针p的地址

指针p可以通过a的地址找到10,那么二级指针pp是不是也能通过指针p的地址找到指针p里面存的a的地址值呢。但是如果我对二级指针pp解引用一次pp指针只能找到a的地址,所以我们解引用两次,就可以得到a了。这就是二级指针的用法。

有没有三级指针呢,准确来说是有的。指针可以无限套娃也就是可以增长到N级指针,只不过我们平常写代码时顶多用到了二级指针。一般情况没人用到三级和三级以上的指针。


3、指针和数组

往期内容我们知道了数组名的地址就是数组首元素地址,以下代码证实这个想法:

#include<stdio.h>

int main()
{
	int arry[3] = { 1,2,3 };
	printf("%p\n", arry);
	printf("%p\n", &arry[0]);
	return 0;
}

输出结果

001AF8F4
001AF8F4 

可见数组名和数组首元素的地址是一样的。那么我们得出的结论是:数组名表示的是数组首元素的地址


我们知道数组名是地址,指针变量指向的也是地址。那我们可不可以用指针来修改数组里面的各个值呢?是可以,我们来看一组代码,通过指针实现一个数组里面每个值都增加1:

#include<stdio.h>

int main()
{
	int arry[] = { 1,2,3,4,5 };
	int n = sizeof(arry) / sizeof(arry[0]);
	int* p = arry;
	for (int i = 0; i < n; i++)
	{
	    arry[i] = *(p + i) + 1;
	}
	for (int j = 0; j < n; j++)
	{
		printf("%d ", arry[j]);
	}
	return 0;
}

输出结果:2 3 4 5 6

以上结果说明了指针和数组不分家。指针p通过地址依次访问了arry里面的各个元素并使各个元素+1了。这就是指针与数组的关系,您学会了吗?


4、指针数组

我们先来玩个文字游戏,指针数组是指针,还是数组呢?答案是数组,就好比好兄弟,好兄弟是好还是兄弟呢,当然是兄弟了。凭啥认为指针数组是数组,我们来看一组代码:

#include<stdio.h>

int main()
{
	int a = 10;
	int b = 11;
	int c = 12;
	int d = 13;
	int* arry[4] = { &a,&b,&c,&d };
	for (int i = 0; i < 4; i++)
	{
		printf("%d ", *arry[i]);
	}
	return 0;
}

输出结果

10 11 12 13

上述代码,arry是一个数组,有四个元素,每个元素是一个整型指针。arry数组里面的指针依次对应着abcd四个值的地址。因此我们认为指针数组就是一个数组。


有一代码,使用一维数组模拟一个三行四列的二维数组:

#include<stdio.h>

int main()
{
	int a[4] = { 2,3,4,5 };
	int b[4] = { 6,7,8,9 };
	int c[4] = { 10,11,12,13 };
	int* arry[3] = { a,b,c };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			printf("%d ", arry[i][j]);
		}
		printf("\n");
	}
	return 0;
}

输出结果

2 3 4
5 6 7
8 9 10

我们已经知道了,数组名就是地址。那么把分别把a、b、c三个数组的数组名存放在指针数组arry里面,这样我们就可以通过这三个数组名访问到各个数组的元素。以上方法使用指针数组实现了一维数组组成二维数组。


所有初识指针内容到这里就结束了,感谢您的观看。

 Never Give Up


初识指针(一)初识指针(二)

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

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

相关文章

Redis数据类型总结

文章目录一、5种数据类型二、常用指令汇总三、应用汇总提示&#xff1a;以下是本篇文章正文内容&#xff0c;Redis系列学习将会持续更新 一、5种数据类型 Redis 数据存储格式&#xff1a;  ● redis 自身是一个 Map ,其中所有的数据都是采用 key : value 的形式存储。  ● 数…

如何设计用户体验测试用例

一、 什么是用户体验 UE&#xff1a; User Experience 用户体验。 用户体验是指用户在使用产品过程中的个人主观感受&#xff0c;即用户在使用一个产品之前、使用过程中、使用后的整体感受&#xff0c;包括行为、情感、喜好、生理和心里反应、成就等各个方面。 通俗的讲用户体…

希望所有计算机学生都知道这些宝藏网站

GitHub GitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持Git作为唯一的版本库格式进行托管&#xff0c;故名GitHub。 作为开源代码库以及版本控制系统&#xff0c;Github拥有超过900万开发者用户。随着越来越多的应用程序转移到了云上&#xff0c;Github已…

数据结构与算法(五) 动态规划

这篇文章来讲动态规划&#xff08;Dynamic Programming&#xff09;&#xff0c;这是一个在面试中很经常出现的题型 1、本质 之前说过&#xff0c;解决算法问题的主流思路就是穷举搜索&#xff0c;即遍历整个搜索空间&#xff0c;找到给定问题的解 只是在某些场景下&#xff…

Python学习 - 异常处理

Python学习 - 语法入门&#xff1a;https://blog.csdn.net/wanzijy/article/details/125287855 Python学习 - 数据类型&#xff1a;https://blog.csdn.net/wanzijy/article/details/125341568 Python学习 - 流程控制&#xff1a;https://blog.csdn.net/wanzijy/article/details…

3dmax网渲云渲染哪个平台费用低?一张图要多少钱多长时间?怎么收费

话说现在的设计师应该没有不知道云渲染的吧&#xff1f;毕竟比起本地渲&#xff0c;云渲染不占本地资源&#xff0c;一次能渲很多张&#xff0c;方便又快捷&#xff0c;有谁不喜欢呢&#xff01;那么这么多的云渲染平台用哪个呢&#xff1f;今天我们就以主流的4个平台为例&…

(STM32)从零开始的RT-Thread之旅--SPI驱动ST7735(4)使用LVGL

上一篇&#xff1a; (STM32)从零开始的RT-Thread之旅--SPI驱动ST7735(3)使用DMA 经过前几章的搭建&#xff0c;底层显示已经没有问题了&#xff0c;现在需要添加上层的库&#xff0c;我选择了比较火的开源GUI库--LVGL。而RT-Thread Studio支持直接添加LVGL代码库的。 在RT-T…

人工智能-4计算机视觉和图像处理01

深度学习简介 机器学习是实现人工智能的一种途径&#xff0c;深度学习是机器学习的一个子集 深度学习相比于机器学习&#xff0c;少了‘手动特征提取’部分&#xff0c;交给网络来处理 深度学习流程&#xff1a;数据输入–训练模型&#xff08;在数据中学习&#xff09;–输出预…

IP请求工具

无缝的 IP 分配和管理 手动将不同子网中的 IP 分配给不同的 IT 管理员&#xff0c;同时遵守配置的不同访问级别可能是一项繁琐的任务。为了简化IP请求和分配的过程&#xff0c;OpUtils为您提供了一个内置的IP请求工具。使用此工具&#xff0c;您的网络管理员不必再等待其 IP 请…

数据库笔记

文章目录01 数据库概述1.1 四个基本概念1.2 数据管理技术的三个阶段1.2.1 人工管理阶段1.2.2 文件系统阶段1.2.3 数据库阶段1.3 数据独立性1.4 数据库的三级模式结构1.4.1 三级模式结构1.4.2 数据库的二级映像与数据独立性02 关系数据库2.1 关系数据结构及形式化定义2.1.1 关系…

论文管理系统(增删查改功能的实现)

目录 一、后端 1.1实体类 1.2paperMapper类 1.3 PaperMapper类 1.4Service层 1.5 Controller层 二、前端 源代码 我们已经实现列表数据了,接下来我们将实现增删查改功能,新增和修改还能够回显 一、后端 1.1实体类 实体类还是我们上一版的列表功能的实现的paper实…

IFD-x 微型红外成像仪探测距离说明

红外热成像仪是用光学镜头来收集被测物体的热辐射能量的&#xff0c;故此探测距离会受镜头视场角 和热成像像素分辨率有关。 假如某成像仪的成像分辨率为 32*32 像素&#xff0c;视场角为 75 度&#xff0c;则可以理解为从镜头发射出 32*321024 条激光来探测 1024 个点的…

数据结构初阶:队列

目录 一、队列的概念和结构 二、队列的实现 定义队列结构 初始化队列 销毁队列 检测队列是否为空 入队列 出队列 获取队列头部元素 获取队列队尾元素 获取队列中有效元素个数 优化 三、测试 四、优化后的全部代码 一、队列的概念和结构 队列:只允许在一端进行插入数据操作…

【区块链】用Python实现一条区块链

用Python实现一条区块链 点击链接获取可执行文件 本文使用 python 实现了一条简单的区块链。主要分两个模块&#xff1a;实现每个区块的结构和相关的方法、实现整条区块链的结构和相关的方法。下面是对这两个模块的描述。 每个区块主要包括两个成员&#xff1a;区块头和区块…

GlobalWebsoket.js 的使用,实现获取实时数据

在称重小程序是使用 GlobalWebsoket 实现获取实时数据前言一、逻辑分析二、实现方式1.方法整体流转分析 -- 初始化并绑定1. onLoad1. init2. getDeviceInfo3. initWebSocket4. setProperties2.方法整体流转分析 -- 解除绑定1. onBackPress2. remoeSubscribe三、参数调用分析四、…

“大数据分析”相比“传统数据分析”优势明显,体现在哪些方面

一、大数据和数据分析的定义&#xff1a; 数据分析&#xff1a;指使用适当的统计分析方法来收集数据&#xff0c;以进行大量数据分析。 大数据分析&#xff1a;指在可承受的时间范围内无法使用常规软件工具捕获&#xff0c;管理和处理的数据集合&#xff1b; 数据分析的核心…

【web渗透思路】任意账号的注册、登录、重置、查看

目录 一、任意用户注册 1.未验证邮箱/手机号 2、不安全验证邮箱/手机号 3.批量注册 4.个人信息伪造 5.前端验证审核绕过 6.用户名覆盖 二、任意用户登录 1、万能密码 2、验证码、密码回显 3、登录检测不安全 三、任意账号重置 1、重置账号名 2、验证码 3、MVC数…

2022年第三季度泛出行行业洞察:泛出行行业正在经历数智化升级的关键时期,用户规模保持平稳增长,行业整体良性发展

易观分析&#xff1a;泛出行行业涵盖综合车主服务、车辆加油充电、网约车、旅游预定、酒店预定、户外出行等领域。当前泛出行领域正在经历传统模式向数智化新模式的转变&#xff0c;智能化升级和服务品质提升在该领域变革中正发挥着积极的作用。未来泛出行领域将在数智化、电动…

Web3:价值投资的范式转移

​潜力博主推荐&#xff0c;点上面关注博主 ↑↑↑ 进化是宇宙中最强大的力量&#xff0c;是唯一永恒的东西&#xff0c;是一切的驱动力。———桥水基金 雷.达利奥 时间拉长&#xff0c;进化才是人类的主旋律。过去&#xff0c;环境的变化是进化的主因。 现在&#xff0c;技…

Servlet | 深度剖析转发和重定向

一&#xff1a;深度剖析转发和重定向 &#xff08;1&#xff09;在一个web应用中通过两种方式可以完成资源的跳转 第一种方式&#xff1a;转发方式 第二种方式&#xff1a;重定向方式 &#xff08;2&#xff09;转发和重定向的区别 区别一&#xff1a;代码上的区别 ①转发 &a…