【时时三省】(C语言基础)通过指针引用数组

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省

数组元素的指针

一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓数组元素的指针就是数组元素的地址。可以用一个指针变量指向一个数组元素。

例如:

int a [ 10 ] = ( 1,3,5,7,9,11,13,15,17,19 );

int * p ;

p = & a [ 0 ];

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

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

C语言中,数组名(不包括形参数组名)代表数组中首元素(即序号为0的元素)的地址。因此,下面两个语句等价:

p=&a[0];

p=a;

注意:程序中的数组名不代表整个数组,只代表数组首元素的地址。上述“p = a;"的作用是“把a数组的首元素的地址赋给指针变量p”,而不是“把数组a各元素的值赋给p”

在定义指针变量时可以对它初始化,如:

int p &a [ 0 ];

它等效于下面两行:

int *p;

p=&a[0];

当然定义时也可以写成

int * p = a ;

它的作用是将a数组首元素(即a [ 0 ])的地址赋给指针变量p(而不是赋值给*p)。

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

在引用数组元素时常常会遇到指针的算术运算。有人会提出问题:对数值型数据进行算术运算(加、减、乘、除等)的目的和含义是清楚的,而在什么情况下需要用到对指针型数据的算术运算呢?其含义是什么?

前已反复说明指针就是地址。对地址进行赋值运算是没有问题的,但是对地址进行算术运算是什么意思呢?显然对地址进行乘和除的运算是没有意义的,实际上也无此必要。那么,能否进行加和减的运算?答案是:在一定条件下允许对指针进行加和减的运算。

那么,在什么情况下需要而且可以对指针进行加和减的运算呢?回答是:当指针指向数组元素的时候。譬如,指针变量p指向数组元素a [ 0 ],我们希望用p +1表示指向下一个元素a1。如果能实现这样的运算,就会对引用数组元素提供很大的方便。

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

加一个整数(用+或+ =),如p +1;

减一个整数(用-或- =),如p -1;

自加运算,如p++,++p;

自减运算,如p--,--p。

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

分别说明如下:

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

现在p指向float型的数组元素,在执行++p时,系统会根据p的基类型为float型而将其值加4,这样,p就指向float型数组的下一个元素。如果p原来指向a [ 0 ],执行++p后p的值改变了,在p的原值基础上加d,这样p就指向数组的下一个元素a [ 1 ]。

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

( 3 ) * ( p + i )或* ( a + i )是p + i或a + i所指向的数组元素,即a [ i ]。例如,* ( p + 5 )或* ( a + 5 )就是a[ 5 ],即:*(p+5),*(a+5)和a[5]三者等价。实际上,在编译时,对数组元素a[i]就是按* ( a + i )处理的,即按数组首元素的地址加上相对位移量得到要找的元素的地址,然后找出该单元中的内容。若数组a的首元素的地址为1000,设数组为float型,则a [ 3 ]的地址是这样计算的:1000 + 3×4 = 1012,然后从1012地址所指向的float型单元取出元素的值,即a [ 3 ]的值。

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

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

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

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

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

相关文章

【WEB】Polar靶场 21-25题 详细笔记

二十一.php very nicephp又是你 ,但是经过这么多次折磨后我感觉我已经有一点抗性了老规矩,先看知识点PHP 序列化是将 PHP 变量(如对象、数组)转换为字符串的过程,便于存储或传输。反序列化则是将字符串还原为原始变量。这在缓存、…

【Guava】1.0.设计虚拟机的方向

【Guava】1.0.设计虚拟机的方向虚拟机是什么?栈式虚拟机栈式虚拟机的优缺点题外话虚拟机是什么? 虚拟机(VirtualMachine, VM)是一种计算机程序或系统,它通过软件模拟物理计算机的硬件运行环境,使得多个操作…

[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的高校实验室资源综合管理系统,推荐!

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本高校实验室资源综合管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大…

Spring Boot:影响事务回滚的几种情况

一、Controller 捕获异常导致事务失效 需求 我们有一个用户注册服务,注册时需要: 创建用户账户分配初始积分发送注册通知 这三个操作需要在同一个事务中执行,任何一步失败都要回滚。 错误示例:Controller 捕获异常导致事务失效 Re…

如何避免分布式爬虫被目标网站封禁?

在分布式爬虫的大规模数据采集场景中,避免被目标网站封禁的核心逻辑是:通过技术手段模拟真实用户行为,降低爬虫行为的可识别性,同时建立动态适配机制应对网站反爬策略的升级。以下从请求伪装、行为控制、资源管理、反爬对抗四个维…

Maven 打包排除特定依赖的完整指南(详细方法 + 示例)

前言 在使用 Maven 构建 Java 项目时,我们常常需要对项目的打包过程进行精细化控制,尤其是希望排除某些特定的依赖库。这可能是为了减小最终构建产物的体积、避免版本冲突,或者仅仅是为了满足不同环境下的部署需求。 本文将详细介绍如何在 Ma…

Terraform `for_each` 精讲:优雅地自动化多域名证书验证

大家好,在云原生和自动化运维的世界里,Terraform无疑是基础设施即代码(IaC)领域的王者。它强大的声明式语法让我们能够轻松地描述和管理云资源。然而,即使是经验丰富的工程师,在面对某些动态场景时也可能会…

C++标准库中各种互斥锁的用法 mutex

示例 仅供参考学习 #include <mutex> #include <shared_mutex> #include <thread> #include <chrono> #include <iostream> #include <vector>// // 1. std::mutex - 基本互斥锁 // void basic_mutex_example() {std::mutex mtx;int cou…

Android Handler机制与底层原理详解

Android 的 Handler 机制是跨线程通信和异步消息处理的核心框架&#xff0c;它构成了 Android 应用响应性和事件驱动模型的基础&#xff08;如 UI 更新、后台任务协调&#xff09;。其核心思想是 “消息队列 循环处理”。 核心组件及其关系Handler (处理器): 角色: 消息的发送…

jQuery JSONP:实现跨域数据交互的利器

jQuery JSONP&#xff1a;实现跨域数据交互的利器 引言 随着互联网的发展&#xff0c;跨域数据交互的需求日益增加。在Web开发中&#xff0c;由于同源策略的限制&#xff0c;直接通过XMLHttpRequest请求跨域数据会遇到诸多问题。而JSONP&#xff08;JSON with Padding&#xff…

Redis集群和 zookeeper 实现分布式锁的优势和劣势

在分布式系统中&#xff0c;实现分布式锁是确保多个节点间互斥访问共享资源的一种常见需求。Redis 集群 和 zookeeper 都可以用来实现这一功能&#xff0c;但它们有着各自不同的优势和劣势。 CAP 理论&#xff1a; 在设计一个分布式系统时&#xff0c;一致性&#xff08;Consis…

如何备份vivo手机中的联系人?

随着vivo移动设备在全球设立7个研发中心&#xff0c;vivo正在进入更多的国家。如今&#xff0c;越来越多的人开始使用vivo手机。以vivo X100为例&#xff0c;它配备了主摄像头和多个辅助摄像头&#xff0c;提供多样化的拍摄选项&#xff0c;并搭载了最新的FunTouch OS&#xff…

python脚本编程:使用BeautifulSoup爬虫库获取热门单机游戏排行榜

BeautifulSoup是一个便捷的解析html页面元素的python库&#xff0c;此处用来写一个简单的爬虫批量抓取国内游戏资讯网站的近期热门单机游戏排行榜。 网页来源如下所示代码 from bs4 import BeautifulSoup import requests# get web page web_url "https://www.3dmgame.co…

C#配置全面详解:从传统方式到现代配置系统

C#配置全面详解&#xff1a;从传统方式到现代配置系统 在软件开发中&#xff0c;配置是指应用程序运行时可调整的参数集合&#xff0c;如数据库连接字符串、API 地址、日志级别等。将这些参数从代码中分离出来&#xff0c;便于在不修改代码的情况下调整应用行为。C# 提供了多种…

数据中台架构解析:湖仓一体的实战设计

目录 一、数据中台与湖仓一体架构是什么 1. 数据中台 2. 湖仓一体架构 3. 湖仓一体在数据中台里的价值 二、湖仓一体架构的核心部件 1. 数据湖 2. 数据仓库 3. 数据集成工具 4. 数据分析与处理引擎 三、湖仓一体架构实战设计 1. 需求分析与规划 2. 数据湖建设 3. …

SQL Server表分区技术详解

表分区概述 表分区是将大型数据库表物理分割为多个较小单元的技术,逻辑上仍表现为单一实体。该技术通过水平分割数据显著提升查询性能,尤其针对TB级数据表可降低90%的响应时间。典型应用场景包含订单历史表、日志记录表等具有明显时间特征的业务数据,以及需要定期归档的审计…

WHIP(WebRTC HTTP Ingestion Protocol)详解

WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;详解 WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;是一种基于 HTTP 的协议&#xff0c;用于将 WebRTC 媒体流推送到媒体服务器&#xff08;如 SRS、Janus、LiveKit&#xff09;。它是为简化 WebRT…

图像噪点消除:用 OpenCV 实现多种滤波方法

在图像处理中&#xff0c;噪点是一个常见的问题。它可能是由于图像采集设备的缺陷、传输过程中的干扰&#xff0c;或者是光照条件不佳引起的。噪点会影响图像的质量和后续处理的效果&#xff0c;因此消除噪点是图像预处理的重要步骤之一。本文将介绍如何使用 OpenCV 实现几种常…

AI的Prompt提示词:英文写好还是中文好?

在与AI人大模型交互时,Prompt(提示词)的质量直接决定了输出的精准度和有效性。一个常见的问题是:究竟是用英文写Prompt好,还是用中文写更好?这并非一个简单的二元选择,而是涉及到语言模型的底层逻辑、表达的精确性以及个人使用习惯的综合考量。 英文Prompt的优势 模型训…

react的条件渲染【简约风5min】

const flag1true; console.log(flag1&&hello); console.log(flag1||hello); const flag20; console.log(flag2&&hello); console.log(flag2||hello); // &&运算符&#xff0c;如果第一个条件为假&#xff0c;则返回第一个条件&#xff0c;否则返回第二…