C语言-数组指针与指针数组

一、简介

        对于使用C语言开发的人来说,指针,大家都是非常熟悉的。数组,大家也同样熟悉。但是这两个组合到一起的话,很多人就开始蒙圈了。这篇文章,就详细的介绍一下这两个概念。

        指针数组数组指针,听起来非常像,但是两者是完全不同的概念。从名字上就可以知道,一个是数组一个是指针

        那如何区分呢?

        最简单的方法,就是根据语句中符号的优先级来。

        优先级关系:( ) > [ ] > *

        有了这个概念后,我们再来看如下两个定义:

int *a[4];
int (*a)[4];

        *a[4]语句中,因为优先级[ ] > *。所以,[ ]就是这个变量的“根”,即数组才是这个变量的本质。所以*a[4]就是数组。因为该数组前面加了取址符 * ,所以,它就是指针数组

        (*a)[4]语句中,因为优先级() > [],所以先看括号内的东西,是*a。这个一看就知道是个指针,所以,这个变量的本质就是个指针。又因为这个指针后面加了[ ]。所以,它是数组指针

        一句话,谁不重要,谁是定语。(中文语法不好的,回去补一补!)人话就是:本质是什么,最后两个字就是什么

        *a[4]本质是数组,那就是指针数组(*a)[4]本质是指针,那就是数组指针

        好啦,概念搞懂了,接下来就是看看其含义了。

        int *a[4]是个数组,那就要干数组的活。指针数组的意思就是,这个数组里面的元素都是指针指针的类型是int,指向的内容也是int型

        int (*a)[4]是个指针,那就要干指针的活。数组指针的意思就是,这个指针,指向了长度为4的数组这个数组的类型是int型

        好了,含义的概念也说完了。是不是感觉还是不懂。没关系,接下来用实例来对以上两个东西介绍一下。

二、指针数组

        在上面的文章中说过,指针数组的本质是数组,数组内的元素都是指针。看如下这个例子

    char a[] = "123";char b[] = "456";char c[] = "789";char d[] = "012";char *p[4];p[0] = a;p[1] = b;p[2] = c;p[3] = d;

        这里定义了一个指针数组char *p[4]。数组内的元素都是指针,所以,把abcd四个地址赋值给指针。

        上面的写法可以用下面这个写法来代替。

char *p[4] = {“123”,“456”,“789”,“012”};

        那以如下的例子来详细讲解一下

    char a[] = "123";char b[] = "456";char c[] = "789";char d[] = "012";char *p[4];LOG_I(TAG,"&p[0] = %d, &p[1] = %d, &p[2] = %d, &p[3] = %d",p[0], p[1], p[2], p[3]);p[0] = a;p[1] = b;p[2] = c;p[3] = d;LOG_I(TAG,"&a = %d, &b = %d, &c = %d, &d = %d",a, b, c, d);LOG_I(TAG,"&p[0] = %d, &p[1] = %d, &p[2] = %d, &p[3] = %d",p[0], p[1], p[2], p[3]);LOG_I(TAG,"p = %d, *p = %d, *(p+1) = %d, *(*(p+1)) = %c, *(*p+1) = %c, **p = %c",p, *p, *(p+1), *(*(p+1)), *(*p+1), **p);LOG_I(TAG,"p[0] = %s, p[1] = %s, p[2] = %s, p[3] = %s",p[0], p[1], p[2], p[3]);

        先看结果

         可以看到,在赋值之前,p[0],p[1],p[2],p[3]的地址都是指向乱地址。赋值之后,地址就与abcd相同。

       从上面的打印,我们可以看到,p与abcd变量的地址都不相同按照数组的概念来说的话,数组p的地址应该与首元素相同。但是这里却不同,相反,*p的内容却与a变量的地址相同。由此我们可以得到如下结论,p实际上是一个地址的地址。而其内容才是元素的地址。再看**p的内容,是1。元素的内容为1,即指向a数组的内容。与我们的结论相同。

        这里需要注意的是 *(p+1) , *(*(p+1)) , *(*p+1)。

        刚才我们得到结论,p实际是一个地址的地址而*p[4]的本质还是一个数组,那么p+1,实际上是指向了第二个元素地址的地址。取内容就是第二个元素的地址。从打印内容可以看到*(p+1)与第二个元素b的地址是相同的。

        有了上面的结论,那就可以推断出, *(*(p+1))就是第二个元素的内容。从打印上可以看到,打印的结果是4,与b数组的第一个元素是能对应上的。

        至于*(*p+1),上面结论是,*p是a数组的地址,其地址+1再取值,即a数组的第二个元素。其打印结果为2,也与结论相对应。

        最后,打印各个元素指针所指向的内容,也就是abcd四个数组的内容。

        因为p是数组,所以不能执行p++的操作

        说了这么多,可能会有人问,指针数组一般用在哪里

        比如说,我们在编程的时候某些地方需要做寻址操作,例如汉字或语音的寻址。因为这些内容的地址是不连续的,但是又不可能每次都去调用寻址。那么就可以一个指针数组,该数组内的指针元素对应各个不同地址的内容。后续我们只需要调用这个指针数组的各个元素,就能调用到不同的地址内容。同样的,这个指针数组各个元素也可以是函数指针,这样,就在同一个数组内,调用不同的回调函数,非常方便。

三、数组指针

        数组指针的本质是指针指向一个数组

        数组指针一般与二维数组配合使用。见如下例子

    int (*p)[5];int a[3][5] = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};p = a;LOG_I(TAG,"&a[0] = %d, a[0] = %d, &a[1] = %d, a[1] = %d, &a[2] = %d, a[2] = %d",&a[0], a[0], &a[1], a[1], &a[2], a[2]);LOG_I(TAG,"&a = %d,&p = %d, p = %d, *p = %d, *(p+1) = %d, *(*(p+1)) = %d, *(*p+1) = %d, **p = %d",&a, &p, p, *p, *(p+1), *(*(p+1)), *(*p+1), **p);p++;LOG_I(TAG,"&a = %d,&p = %d, p = %d, *p = %d, *(p+1) = %d, *(*(p+1)) = %d, *(*p+1) = %d, **p = %d",&a, &p, p, *p, *(p+1), *(*(p+1)), *(*p+1), **p);

        先看结果

        先创建一个数组指针(*p)[5]。这个指针指向长度为5的数组

        把a的地址赋值给数组指针p。

        跟一般的指针一样,&p与p是不同的。但是这里可以发现p与*p相同。一般来说,对于指针而言,p是地址,而*p是该地址的内容。这里看到p与*p相同,且都与a数组的地址相同。这里可以按照数组a与&a理解

        *(p+1)。与正常的指针一样,p+1即移动到下一个地址,不同的是因为该数组指针指向的是一个长度为5的数组,所以p+1则直接移动5个元素的长度。从打印的结果中也可以看到*(p+1)与 a[1]的地址相同

        *(*(p+1))。上述结论中,*(p+1)表示二维数组a[1]的地址,那么取值就是取该数组的值。为6.

        *(*p+1)。上述结论中,*p是二维数组a[0]的地址,那么*p+1则为a[0]数组的第二个元素的地址。*(*p+1)则表示取值,为2。

        **p。上述结论中,*p是二维数组a[0]的地址,那么*p则为a[0]数组的第一个元素的地址。**p则表示取值,为1。

        因为p的本质是个指针,那么是可以进行p++的操作的。p++将直接移动到数组长度的位置,即从a[0]直接移动到a[1]。所以**p的值为6。

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

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

相关文章

【服务器数据恢复】通过reed-solomon算法恢复raid6数据的案例

服务器数据恢复环境: 一台网站服务器中有一组由6块磁盘组建的RAID6磁盘阵列,操作系统层面运行MySQL数据库和存放一些其他类型文件。 服务器故障: 该服务器在工作过程中,raid6磁盘阵列中有两块磁盘先后离线,不知道是管理…

在Linux操作系统的ECS实例上安装hadoop

目录 1. java(jdk)2. Hadoop3. 配置文件4. 启动Hadoop服务(搭建伪分布式环境) 1. java(jdk) yum list java* :列出所有名称中包含“java”字样的软件包yum install java-1.8.0-openjdk.x86_64:选择自己想要的版本。这里我选择jav…

DataGrip 2023:让数据库开发变得更简单、更高效 mac/win版

JetBrains DataGrip 2023是一款功能强大的数据库IDE,专为数据库开发和管理而设计。通过DataGrip,您可以连接到各种关系型数据库管理系统(RDBMS),并使用其提供的一组工具来查询、管理、编辑和开发数据库。 DataGrip 2023 软件获取 DataGrip 2…

分散的产品开发团队

分散的产品开发团队指的是各个团队或成员在地理位置上分布在不同地方,通过互联网和现代通讯技术进行协作和沟通,以共同完成产品开发任务的团队模式。 这种团队模式的优势在于可以充分利用各地的人才资源,降低团队的管理和协作成本&#xff0…

【Ubuntu】使用WSL安装Ubuntu

WSL 适用于 Linux 的 Windows 子系统 (WSL) 是 Windows 的一项功能,可用于在 Windows 计算机上运行 Linux 环境,而无需单独的虚拟机或双引导。 WSL 旨在为希望同时使用 Windows 和 Linux 的开发人员提供无缝高效的体验。安装 Linux 发行版时&#xff0c…

云HIS系统源码,基于云计算技术的B/S架构的云HIS系统,二甲医院信息管理系统

云HIS系统源码,采用云端SaaS服务的方式提供 基于云计算技术的B/S架构的云HIS系统,采用云端SaaS服务的方式提供,使用用户通过浏览器即能访问,无需关注系统的部署、维护、升级等问题,系统充分考虑了模板化、配置化、智能…

vscode + wsl2 + xmake快速构建c语言编译调试环境

前言 使用这一套是我觉得最方便的,wsl2使得我可以不用脱离windows,且无需安装庞大且臃肿虚拟机。vscode让我可以更加方便快捷的编辑代码,而xmake是一站式的工程构建工具且作者就是中国人文档啥的群啥的都是中文,比起cmake makefi…

python统计分析——线性模型的预测和评估

参考资料:用python动手学统计学 1、导入库 # 导入库 # 导入数据处理的库 import numpy as np import pandas as pd import scipy as sp from scipy import stats # 导入绘图的库 from matplotlib import pyplot as plt import seaborn as sns sns.set() # 导入估计…

BERT学习笔记

论文:《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》,2019 代码:[tensorflow],[pytorch] 来源:李沐精度BERT 0、摘要 与之前模型的区别: GPT考虑的是一个单向…

OLTP、OLAP与HTAP、HSAP详解

HTAP、HSAP是OLAP与OLTP综合需求驱动下的新的数据库系统,既满足事务处理,又满足大规模分析查询,并且是基于一套系统下实现。 本节首先我们要了解服务于分析的区别。相当多从应用角度对数据处理分类的划分,大致可以分为Transactio…

计算机网络-网络互联与互联网(一)

1.常用网络互联设备: 1层物理层:中继器、集线器2层链路层:网桥、交换机3层网络层:路由器、三层交换机4层以上高层:网关 2.网络互联设备: 中继器Repeater、集线器Hub(又叫多端口中继器&#xf…

PyTorch概述(二)---MNIST

NIST Special Database3 具体指的是一个更大的特殊数据库3;该数据库的内容为手写数字黑白图片;该数据库由美国人口普查局的雇员手写 NIST Special Database1 特殊数据库1;该数据库的内容为手写数字黑白图片;该数据库的图片由高…

Django学习记录04——靓号管理整合

1.靓号表 1.1 表结构 1.2 靓号表的构造 class PrettyNum(models.Model): 靓号表 mobile models.CharField(verbose_name"手机号", max_length11)# default 默认值# null true,blank true 允许为空price models.IntegerField(verbose_name"价…

学校档案室管理制度内容

学校档案室管理制度是指对学校档案室进行管理的规定和流程。以下是一个示例的学校档案室管理制度的内容: 1.档案室的管理部门和责任人员: 学校档案室由学校行政部门负责管理,行政部门指定专门的档案管理员负责档案室的日常管理工作。 2.档案室…

ElasticSearch之单值多字段查询以及dis max query

写在前面 在查询中经常有这样的查询场景,我们只有一个输入框,但是输入的值需要同时对多个字段进行查询,这就是单值多字段的查询,像下图: 1:例子 首先来准备测试数据: DELETE blogs PUT /bl…

记录 | docker内执行apt update报错GPG error

1. 执行 sudo apt-get update 命令时遇到这个错误,是服务器没有这个公钥的意思 rootadmin:~# sudo apt-get update Get:1 https://download.docker.com/linux/ubuntu focal InRelease [36.2 kB] Err:1 https://download.docker.com/linux/ubuntu focal InRelease T…

基于Python网络爬虫的IT招聘就业岗位可视化分析推荐系统

文章目录 基于Python网络爬虫的IT招聘就业岗位可视化分析推荐系统项目概述招聘岗位数据爬虫分析系统展示用户注册登录系统首页IT招聘数据开发岗-javaIT招聘数据开发岗-PythonIT招聘数据开发岗-Android算法方面运维方面测试方面招聘岗位薪资多维度精准预测招聘岗位分析推荐 结语…

Linux之ACL访问控制列表

一、ACL权限的介绍 1.1 什么是ACL 访问控制列表(ACL)是一种网络安全技术,它通过在网络设备(如路由器、交换机和防火墙)上定义一系列规则,对进出接口的数据包进行控制。这些规则可以包含“允许”&…

【Java EE初阶二十四】servlet的深入理解

1. Servlet API 的学习 下面主要学习这三个类,就已经可以完成 Servlet 的大部分开发了; 1. Httpservlet 2. HttpServletRequest 3. HttpServletResponse 2. Httpservlet的学习 2.1 Httpservlet在tomcat的工作原理 写一个 Servlet 代码,往往都…

跟随realworldCTF,做一个http网络协议黑客

前言 本报告旨在对RealWorldCTF 2024体验赛中的Pwn方向题目——"Be-an-HTPPd-Hacker"进行深入解析和讲解。该题目涉及一个十一年前的项目,其基于C语言实现了HTTP协议。我们将通过对该协议进行栈溢出攻击,探索真实世界中的攻击手法,…