通过指针引用数组的几种方法的原理和差异;以及利用指针引用数组元素的技巧

news2024/11/19 7:48:00

关于地址,指针,指针变量可以参考这篇文章:

地址,指针,指针变量是什么?他们的区别?符号(*)在不同位置的解释?_juechen333的博客-CSDN博客icon-default.png?t=N176https://blog.csdn.net/qq_57342311/article/details/129225045关于指针变量作为函数参数可以参考这篇文章:

指针变量作为函数参数详解,形参和实参之间的值传递如何传递?如何改变指针变量所指向的变量?_juechen333的博客-CSDN博客icon-default.png?t=N176https://blog.csdn.net/qq_57342311/article/details/129231880

目录

一、数组元素的指针

1.1引入

1.2实例

二、在引用数组元素时指针的运算

2.1引入

2.2实例

2.3详细说明

三、通过指针引用数组元素

3.1引入

3.2举例说明

3.3拓展


一、数组元素的指针

1.1引入

一个数组包含若干元素,每个数组元素都占用存储单元,所以他们都有相应的地址,所谓数组元素的指针就是数组元素的地址。

1.2实例

下面用指针变量指向一个数组元素

int a[10] = { 1,2,3,4,5,6,7,8,9,10 };	//定义包含10个数据的整型数组
int* p;		//定义1个整型指针变量
p = &a[0];	//将数组元素a[0]的地址赋值指针变量

以上是将指针变量 p 指向 a 数组的第 0 号元素。

引用数组元素可以使用下标法,也可以使用指针法,即通过指向数组元素的指针找到所需的元素,使用指针法能使目标程序质量高(占内存少,运行速度快)。

在 C 语言中,数组名(不包含形参数组名)代表数组中首元素(即序号为 0 的元素)的地址,所以下面两个语句等价

p = &a[0];		//p的值是a[0]的地址
p = a;			//p的值是数组a首元素(即a[0])的地址

注意:数组名不代表整个数组,只代表数组首元素的地址。

二、在引用数组元素时指针的运算

2.1引入

可以对数值型数据进行算数运算,那么可以对指针型数据进行算数运算吗?指针就是地址,显然对地址进行乘和除是没有意义的,只有在一定条件下进行的加和减才有意义。

当指针指向数组元素的时候,能够对指针进行加和减运算;例如指针变量 p 指向数组元素 a[0],则 p+1表示指向下一个数组元素 a[1]。

2.2实例

在指针已指向一个数组元素时,可以对指针进行以下运算:

①加一个整数( p + i ),如 p += 1;

②减一个整数( p - i ),如 p -= 1;

③自加运算,如 p++

④自减运算,如 p--

⑤两个指针相减,如 p1 - p2 (只有p1和p2都指向同一个数组中的元素时才有意义)

2.3详细说明

(1)如果指针变量 p 已指向数组中的一个元素,则 p+1 指向同一数组中的下一个元素,p-1 指向同一数组中的上一个元素。执行 p+1 时并不是将 p 的值(地址)简单地加 1 ,而是加上一个数组元素所占用的字节数。例如,数组元素是 float 型,每个元素占4个字节,则 p+1 意味着使 p 的值(地址)加4个字节,以使它指向下一元素。p+1所代表的地址实际上是 p+1×d ,d 是一个数组元素所占的字节数(在Visual C++ 中,对 int 型,d=4;对 float 和 long 型,d=4;对 char 型,d=1 )。若 p 的值是2000,则 p+1的值不是2001,而是2004。

那么系统怎么知道要把这个 1 转换为 4,然后与 p 的值相加呢?因为在定义指针变量时必须要指定基类型,如:float* p。

(2)如果 p 的初值为 &a[0],则 p+i 和 a+i 就是数组元素 a[i] 的地址,或者说,它们指向 a 数组序号为 i 的元素。 a 代表数组首元素的地址,a+1 也是地址,它的计算方法同 p+1 ,实际地址为 a+1× d。例如,p+9 和 a+9 的值是 &a[9],它指向a[9]。

(3)*(p+i) 或 *(a+i) 是 p+i 或 a+i 所指向的数组元素,即 a[i],例如 *(p+5),*(a+5) 和 a[5] 三者等价,实际上,在编译时,对数组元素 a[i] 就是按 *(a+i) 处理的,即按数组首元素的地址加上相对位移量得到要找元素的地址,然后取出存储单元中的内容。

[ ]实际上是变址运算符,即将 a[i] 按 a+i 计算地址,然后找出此地址单元中的值。

(4)如果指针变量 p1 和 p2 都指向同一数组中的元素,如执行 p2 - p1,结果是 p2 - p1 的值(两个地址之差)除以该数组元素类型所占的字节长度。假设,p2 指向实型数组元素  a[5],p2 的值为2020;p1 指向 a[3],其值为2012,则 p2-p1 的结果是 (2020-2012)/4 = 2 。这个结果是有意义的,表示 p1 所指向的元素与 p2 所指的元素之间差 2 个元素。这样就不需要具体地知道p1和 p2的值,然后去计算它们的相对位置,而是直接用 p2-p1 就可知道它们所指元素的相对距离。

两个地址不能相加,如 p1+p2 是无实际意义的。

三、通过指针引用数组元素

3.1引入

引用数组元素,存在下面两种方法:

①下标法,如 a[i] ;

②指针法(数组名法和指针变量法),如 *(a+i) 或 *(p+i) ,其中 a 是数组名,p 是指向数组元素的指针变量,其初值为 p=a;

3.2举例说明

有一个整型数组 a,有10个元素,要求输出数组的全部元素

(1)下标法

#include<stdio.h>
int main()
{
	int a[10] = { 1,3,5,7,9,2,4,6,8,10 };
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", a[i]);	//通过下标表示
	}
	printf("\n");
	return 0;
}

(2)通过数组名和元素序号计算数组元素的地址

#include<stdio.h>
int main()
{
	int a[10] = { 1,3,5,7,9,2,4,6,8,10 };
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(a + i));	//通过数组名和元素序号计算
	}
	printf("\n");
	return 0;
}

(3)用指针变量指向数组元素

#include<stdio.h>
int main()
{
	int a[10] = { 1,3,5,7,9,2,4,6,8,10 };
	int* p;
	for (p = a; p < (a + 10); p++)
	{
		printf("%d ", *p);		//用指针指向当前的数组元素
	}
	printf("\n");
	return 0;
}

三种方法的比较:

①第(1)和第(2)种方法的执行效率是相同的,编译系统将 a[i] 转换为 *a[i+1] 处理的,第(3)种方法比前面两种更快,用指针直接指向元素,不必每次都重新计算地址,大大提高执行效率。

②用下标法比较直观,能直接知道是第几个元素;用地址法或指针变量的方法不直观,难以很快的判断出当前处理的是哪一个元素。

需要注意的是:不能通过改变数组名a的方式(例如:a++ )来改变所指向的变量,因为 a 代表的是数组首元素的地址,他是一个指针型常量,它的值是固定不变的。

3.3拓展

(1)指向数组元素的指针变量也可以带下标,如 p[i] ;因为程序在编译时,对下标的处理方法是转换为地址,p[i] 处理成 *(p+i) ,需要注意的是此时 p[i] 的指向,若 p 指向 a[0],则 p[2] 代表 a[2],若 p[i] 指向 a[3],则 p[2] 代表 a[5],建议少用,容易出错。

(2)利用指针引用数组元素,比较灵活方便,可以使用一些技巧使程序更加简洁。

① *p++ :由于++和 * 同优先级,结合方向为自右而左,因此它等价于 *(p++),即先引用p的值,实现 *p 的运算,然后再使 p 自加1。

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

② *(p++) 和 *(++p) 的作用不相同,前者先取 *p 的值,然后再自加 1,后者先使 p+1,再取 *p 的值。

#include<stdio.h>
int main()
{
	int a[3] = { 2,5,8 };
	int b[3] = { 2,5,8 };
	int* p, * q;
	for (p = a; p < (a + 3); )
	{
		printf("%d ", *(p++));
	}
	printf("\n");
	for (q = b; q < (b + 3); )
	{
		printf("%d ", *(++q));
	}
}

后着因为没有定义数组 b 的第 4 个元素 b[4],所以指向了一个不确定的位置。

③ (*p)++ 和 ++(*p) 作用不相同,但都是先得到 (*p) 所指向元素的值,前者先把 (*p) 所指向的元素值作为表达式的值后,再自加 1;后着是自加 1 后再作为表达式的值。但需要注意的是:他们都是使 p 所指向的元素加 1 ,而不是使指针 p 的值加 1 。

#include<stdio.h>
int main()
{
	int a[3] = { 2,5,8 };
	int b[3] = { 2,5,8 };
	int* p, * q;
	for (p = a; p < (a + 3); p++)
	{
		printf("%d", (*p)++);
	}
	printf("\n");
	for (q = b; q < (b + 3); q++)
	{
		printf("%d", ++(*q));
	}
}

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

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

相关文章

nginx http模块

模块依赖2. 模块的初始化2.1 location的定义location的定义包含以下几种location [ | ~ | ~* | ^~ ] uri { ... } location name { ... }:表示精确匹配&#xff0c;只有请求的url路径与后面的字符串完全相等时&#xff0c;才会命中&#xff0c;不支持location嵌套~&#xff1a…

有免费的PDF转Word吗?值得收藏的7个免费 PDF转Word工具请收好

PDF 和 DOC 是人们在工作中广泛使用的两种最流行的文档格式。PDF 是 Adobe 的便携式文档格式&#xff0c;DOC 是 Microsoft 的 Word 文档格式。PDF 是一种更安全可靠的文件格式&#xff0c;因为它很难编辑 PDF 文件&#xff0c;但是有一些称为 PDF 编辑器的工具可用于编辑 PDF …

【Linux】工具(4)——make/Makefile

本期博客我们的任务就是搞懂自动化构建工具——make/Makefile一、什么是make/Makefile&#x1f4cc;make是一个命令工具&#xff0c;是一个解释makefile中指令的命令工具&#xff0c;一般来说&#xff0c;大多数的IDE都有这个命令&#xff0c;比如&#xff1a;Delphi的make&…

设计模式之创建型模式

一、设计模式分类二、创建型模式1、单例模式1.1 饿汉式&#xff08;静态变量&#xff09;1.2 饿汉模式&#xff08;静态代码块&#xff09;1.3 懒汉式&#xff08;线程不安全&#xff09;1.4 懒汉式&#xff08;线程安全&#xff0c;同步方法&#xff09;1.5懒汉式&#xff08;…

PHP语言

一、PHP简介 什么是 PHP&#xff1f; PHP 是强有力的服务器端脚本语言 PHP 是免费的&#xff0c;并且使用广泛 PHP能够包含文本、HTML、CSS以及PHP代码&#xff0c;在服务器上执行&#xff0c;结果以纯文本返回浏览器。PHP是从C和Perl发展而来的一种非常简单的语言&#xff…

考研流程,可以进来转一转(考研你不知道的事情)(详细版)

之前有听过好多人说要考研&#xff0c;那么&#xff0c;考研的信息&#xff0c;如何获取呢&#xff0c;考研都有哪些流程呢。 初试开始到考试&#xff1a;↓ 1、了解考研信息。 2、确定自己要报考的专业。&#xff08;本专业or跨考&#xff09; 3、选择地区 4、选择要报考的学…

TAURI初体验

TAURI初体验 - 一个聊天机器人demo前言一、搭建Tauri apps二、引入库相关vue库三、 业务逻辑1.页面布局2. openai的初始化3. text-davinci-003模型4.gpt-3.5-turbo模型总结前言 一直使用Electron开发桌面应用&#xff0c;时间长了也就腻了。很早之前就关注了Tauri&#xff0c;趁…

尚硅谷SpringCloud Alibaba

1. Cloud Alibaba简介2.Nacos简介和下载3.Nacos安装4.Nacos之服务提供者注册5.Nacos之服务消费者注册和负载6.Nacos服务注册中心对比提升7.Nacos之服务配置中心8.Nacos之命名空间分组和DataID三者关系9.Nacos之DataID配置10.Nacos之Group分组方案11.Nacos之Namespace空间方案12…

基于支持向量机SVM的分类预测,基于SVM的雷击故障识别

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 SVM应用实例,基于SVM的雷击故障分类预测 支持向量机SVM的详细原理 SVM的定义 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空…

主流机器学习平台调研与对比分析

梗概 本报告主要调研目前主流的机器学习平台&#xff0c;包括但不限于Amazon的Sage maker&#xff0c;Alibaba的PAI&#xff0c;Baidu的PaddlePaddle。对产品的定位、功能、实践、定价四个方面进行详细解析&#xff0c;并通过标杆对比分析提出一套机器学习平台评价体系&#x…

案例总结之——redis缓存不一致的问题

1.是什么&#xff1f; Redis&#xff1a;Remote Dictionary Server&#xff0c;即远程字典服务 支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API。Redis 是当前互联网世界最流行的 NoSQL&#xff08;Not Only SQL&#xff09;数据库…

js实现懒加载 最简单

实现前得先知道一下js里的几个高度&#xff1a; 视口高度&#xff1a;document.documentElement.clientHeight 滚动高度&#xff1a;document.documentElement.scrollTop || document.body.scrollTop 元素距离最顶端高度&#xff1a;dom元素.offsetTop 先说一下思路&#xff1…

k8s之list-watch,节点调度以及亲和性

一、list-watch机制1.1 list-watch介绍Kubernetes 是通过 List-Watch 的机制进行每个组件的协作&#xff0c;保持数据同步的&#xff0c;每个组件之间的设计实现了解耦。用户是通过 kubectl 根据配置文件&#xff0c;向 APIServer 发送命令&#xff0c;在 Node 节点上面建立 Po…

【mmdeploy部署系列】使用Tensorrt加速部署mmpose人体姿态库

【mmdeploy部署系列】使用Tensorrt加速部署mmpose人体姿态库0.引言1.安装mmcv2.使用mmpose&#xff08;1&#xff09;安装mmpose&#xff08;2&#xff09;运行mmpose3.使用mmdeploy&#xff08;1&#xff09;安装ppl.cv&#xff08;2&#xff09;编译安装mmdeploy&#xff08;…

【手把手一起学习】(八) Altium Designer 20修改和自定义原理图标题栏

1 修改原理图标题栏 直接对原理图标题栏属性进行修改&#xff0c;操作如图所示&#xff1a; 修改后&#xff0c;并不会显示&#xff0c;故该方法不可用&#xff1a; 正确的操作如下&#xff0c;先选择合适的模板&#xff1a; 然后&#xff0c;进行属性的修改&#xff1a; 此时…

Python3中ConfigArgParse模块的使用

ConfigArgParse是一个可以替换argparse的插件&#xff0c;可通过"pip install configargparse"直接安装,允许通过配置文件或环境变量设置选项.最新版本为1.5.3&#xff0c;源码地址为:https://github.com/bw2/ConfigArgParse, License为MIT. Python中的命令行…

分布式-分布式高可用笔记

高可用的保障方式 双十一限制退款 从业务角度考虑&#xff0c;由于活动期间流量巨大&#xff0c;订单产生数量过大&#xff0c;需要节省平台和商家的人力资源&#xff0c;节省库存盘点等工作&#xff1b;退款处理并不是核心流程&#xff0c;在双十一当天&#xff0c;商家也没…

vbscriptaspsql常用代码整理

1、前言 因为目前工作中一直有用到vbscript和asp和sql&#xff0c;所以就把一些常用的语法代码整理了一下。 2、vbscript 2.1、do while循环&if else&#xff08;遍历结果集&#xff09; Dim rs do while not rs.Eof rs.eof表示结果集无法获取更多的数据即&#xff08;…

呼吸机方案 以 MM32F3270 为主控板,MM32SPIN05PF 为电机控制主控

呼吸机的作用是让氧气进入肺部并排出二氧化碳&#xff0c;帮助病患顺利呼吸。呼吸机连接一条管子到患者的嘴或鼻子&#xff0c;氧气量可以通过监视器加以控制。 基于灵动微控制器的呼吸机&#xff0c;以 MM32F3270 为主控板&#xff0c;MM32SPIN05PF 为电机控制主控&#xff1…

【LeetCode每日一题】——605.种花问题

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【时间频度】九【代码实现】十【提交结果】一【题目类别】 贪心算法 二【题目难度】 简单 三【题目编号】 605.种花问题 四【题目描述】 假设有一个很长…