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://www.mzph.cn/news/699119.shtml

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

相关文章

PyTorch概述(二)---MNIST

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

互联网广告投放与IP地理位置定位

随着互联网的发展和普及,互联网广告投放成为各行业推广营销的重要方式之一。而结合IP地理位置定位技术,可以实现精准定向,提高广告投放的效果和精准度。IP数据云将探讨互联网广告投放与IP地理位置定位的关系,分析其优势和应用场景…

动态规划算法学习(基础)

做题步骤: 确定dp数组的含义(一维或者二维) 获取递推公式 dp数组如何初始化 确定遍历顺序 打印dp数组(检查) 题目: 1. 斐波那契数 509 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 …

留子厨房开发日志

以下记录了使用go语言框架Beego,Mysql数据库,Redis数据库实现一个点菜/菜谱应用API的全过程。 技术方案 github地址 数据库设计 新建数据库: CREATE DATABASE menu;新建数据表: CREATE TABLE menu ( id int(10) unsigned NOT …

2024 CKS 题库 | 11、AppArmor

不等更新题库 CKS 题库 11、AppArmor Context: APPArmor 已在 cluster 的工作节点node02上被启用。一个 APPArmor 配置文件已存在,但尚未被实施。 Task: 在 cluster 的工作节点node02上,实施位于 /etc/apparmor.d/nginx_apparmor 的现有APPArmor 配置…

Python 实现 ADTM 指标计算:股票技术分析的利器系列(9)

Python 实现 ADTM 指标计算:股票技术分析的利器系列(9) 介绍算法解释 核心代码rolling函数介绍计算 DTMnp.where 使用介绍np.maximum 计算 DBM计算 STM计算 SBM计算 ADTM 完整代码 介绍 ADTM(动态买卖气指标)是一种用…

C++奇怪的 ::template

答疑解惑 怎么会有::template的写法 起初 在阅读stl的源码的时候&#xff0c;发现了一条诡异的代码 // ALIAS TEMPLATE _Rebind_alloc_t template<class _Alloc,class _Value_type> using _Rebind_alloc_t typename allocator_traits<_Alloc>::template rebind…

【misc | CTF】攻防世界 simple_transfer

天命&#xff1a;这题其实不简单啊 拿到流量包&#xff0c;丢进去wireshare&#xff0c;题目都说了flag在里面 ctrl f 直接搜索字符串 右键&#xff0c;追踪流 -> TCP流 查找 .pdf 文件&#xff0c;其实这里思路是比较奇怪的&#xff0c;毕竟是的确比较多内容&#xff0c…

基于PostGIS的慢查询引起的空间索引提升实践

目录 前言 一、问题定位 1、前端接口定位 2、后台应用定位 3、找到问题所在 二、空间索引优化 1、数据库查询 2、创建空间索引 3、geography索引 4、再看前端响应 总结 前言 这是一个真实的案例&#xff0c;也是一个新入门的工程师很容易忽略的点。往往在设计数据库的…

NestJS入门4:MySQL typeorm 增删改查

前文参考&#xff1a; NestJS入门1 NestJS入门2&#xff1a;创建模块 NestJS入门3&#xff1a;不同请求方式前后端写法 1. 安装数据库相关模块 npm install nestjs/typeorm typeorm mysql -S 2. MySql中创建数据库 ​ 3. 添加连接数据库代码 app.module.ts ​ import { M…

给自己留个备忘,blender是右手坐标系

所谓右手坐标系&#xff0c;就是三个轴的方向和右手三根手指的方向一致&#xff08;当然&#xff0c;有要求的&#xff0c;这个要求是大拇指指向x轴方向&#xff0c;食指指向y轴方向,中指指向z轴方向&#xff09;。 不过blender默认是z轴朝上的&#xff0c;如下图。 右手坐标系…

element导航菜单el-menu添加搜索功能

element导航菜单-侧栏&#xff0c;自带的功能没有搜索或者模糊查询。 找了找资料 找到一个比较可行的&#xff0c;记录一下&#xff1a; //index.vue的代码 <div style"overflow:auto"><el-menu :default-active"$route.path":default-openeds&…

<网络安全>《49 网络攻防专业课<第十三课 - 华为防火墙的使用(2)>

6 防火墙的防范技术 6.1 ARP攻击防范 攻击介绍 攻击者通过发送大量伪造的ARP请求、应答报文攻击网络设备&#xff0c;主要有ARP缓冲区溢出攻击和ARP拒绝服务攻击两种。 ARP Flood攻击&#xff08;ARP扫描攻击&#xff09;&#xff1a;攻击者利用工具扫描本网段或者跨网段主机时…

构造器详解

定义: 是一种特殊类型的方法&#xff0c;用于创建对象时初始化对象的状态。 使用new关键字创建对象 构造器特点: 1.和类名相同 2.没有返回值 public class Person {String name;public Person() {this.name"John";}}public class Test {public static void main…

vue2+element医院安全(不良)事件报告管理系统源代码

目录 安全不良事件类型 源码技术栈 医院安全&#xff08;不良&#xff09;事件报告管理系统采用无责的、自愿的填报不良事件方式&#xff0c;有效地减轻医护人员的思想压力&#xff0c;实现以事件为主要对象&#xff0c;可以自动、及时、实际地反应医院的安全、不良、近失事件…

测试环境搭建整套大数据系统(六:搭建sqoop)

一&#xff1a;下载安装包 https://archive.apache.org/dist/sqoop/ 二&#xff1a;解压修改配置。 tar -zxvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C /opt cd /opt mv sqoop-1.4.7.bin__hadoop-2.6.0/ sqoop-1.4.7修改环境变量 vi /etc/profile#SQOOP_HOME export SQOOP_…

nginx-------- 高性能的 Web服务端 (四)

一、高级配置 1 .1网页的状态页 基于nginx 模块 ngx_http_stub_status_module 实现&#xff0c;在编译安装nginx的时候需要添加编译参数 --with-http_stub_status_module&#xff0c;否则配置完成之后监测会是提示语法错误注意: 状态页显示的是整个服务器的状态,而非虚拟主机…

【Android 性能优化:内存篇】——ExoPlayer 释放后内存没有恢复问题探索

背景 最近笔者承接项目的内存优化指标&#xff0c;在内存调研的过程中发现项目中视频播放结束后&#xff0c;内存没有恢复到播放前到水平。项目中用的 EXO 版本为2.19.1&#xff0c;并且笔者自己也写了个简单的 Demo&#xff0c;发现也是如此。虽然有一些偏门方法可以优化&…

4 buuctf解题

[CISCN 2019 初赛]Love Math1 打开题目 题目源码 <?php error_reporting(0); //听说你很喜欢数学&#xff0c;不知道你是否爱它胜过爱flag if(!isset($_GET[c])){show_source(__FILE__); }else{//例子 c20-1$content $_GET[c];if (strlen($content) > 80) {die("…

无人机的视频图传技术

在操控无人机时&#xff0c;视频图传技术显得尤为关键。通过这项技术&#xff0c;无人机的摄像头所捕捉的画面能实时回传至遥控器&#xff0c;使操作者全面掌握无人机的拍摄情况。同时&#xff0c;无人机图传技术也是衡量无人机性能的重要标准&#xff0c;它关乎飞行距离与时间…