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

news2024/10/6 2:31:40

一、简介

        对于使用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.coloradmin.cn/o/1466860.html

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

相关文章

Stable Diffusion 模型分享:Realisian(现实、亚洲人)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 Realisian 是由多个模型合并而来,是一个现实模型,可以绘制美丽的亚…

HarmonyOS学习--三方库

文章目录 一、三方库获取二、常用的三方库1. UI库:2. 网络库:3. 动画库: 三、使用开源三方库1. 安装与卸载2. 使用 四、问题解决1. zsh: command not found: ohpm 一、三方库获取 在Gitee网站中获取 搜索OpenHarmony-TPC仓库,在t…

uniapp_微信小程序自定义顶部导航栏和右侧胶囊对齐(不对齐来打我)

一、想要的效果 思路首先开启自定义导航栏&#xff0c;取消自带的导航栏&#xff0c;然后计算胶囊的高度和标题对齐 二、成品代码 1、首先再你需要居中的代码添加以下style <view class"header":style"{paddingTop:navBarTop px,height:navBarHeight px,…

Excel 面试题及答案(2)

一、VLOOKUP+IF案例: A1 :根据左侧数据源,按姓名匹配《职级》,仅限用函数,不能做任何辅助A2 :根据左侧数据源,按姓名匹配《部门》,仅限用函数,不能做任何辅助A3 :根据右侧考核规则,匹配《绩效比例》,用函数完成(可适当做辅助的单元格区域) =VLOOKUP(F8,IF({1,0},…

【笔记】【开发方案】APN 配置参数 bitmask 数据转换(Android KaiOS)

一、参数说明 &#xff08;一&#xff09;APN配置结构对比 平台AndroidKaiOS文件类型xmljson结构每个<apn>标签是一条APN&#xff0c;包含完成的信息层级数组结构&#xff0c;使用JSON格式的数据。最外层是mcc&#xff0c;其次mnc&#xff0c;最后APN用数组形式配置&am…

VirtualBox+Vagrant快速搭建Centos7

目录 安装VirtualBox&#xff1a; 安装Vagrant&#xff1a; 创建Vagrant项目目录&#xff1a; 初始化Vagrant配置文件&#xff1a; 本地Vagrantfile中的镜像名称&#xff1a; 启动虚拟机&#xff1a; SSH登录虚拟机&#xff1a; 备注&#xff1a;安装镜像的另一种方式是…

【MATLAB】 EWT信号分解+FFT傅里叶频谱变换组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 展示出图效果 1 EWT分解算法 EWT分解算法是一种基于小波变换的信号分解算法&#xff0c;它可以将信号分解为一系列具有不同频率特性的小波分量。该算法的基本思想是将信号分解为多个不同尺度的小波分量&#xff0c;并对…

展锐S8000安卓核心板参数_紫光展锐5G核心板模块定制方案

展锐S8000核心板模块是基于八核S8000平台开发设计的&#xff0c;采用了先进的6nm EUV制程技术。搭载了全新的智能Android 13操作系统&#xff0c;展现出超强的画面解析能力和高性能双通道MIPI&#xff0c;拥有120Hz高刷新率&#xff0c;独立NPU和3.2TOPS Al算力&#xff0c;同时…

2024年数学建模美赛详细总结以及经验分享

前言&#xff1a; 本文记录与二零二四年二月六日&#xff0c;正好今天是数学建模结束&#xff0c;打算写篇文章记录一下整个过程&#xff0c;以及一些感受、还有经验分享。记录这个过程的原因就是我在赛前&#xff0c;在博客上找了很久&#xff0c;也没有像我这么类似记…

2024,中国零售行业数字化走到哪了?

对于如今的中国零售业数字化而言&#xff0c;仍有许多亟待解决的问题&#xff0c;其像一根根“鱼刺”&#xff0c;卡在零售企业增长的“喉咙”中。 作者|斗斗 编辑|皮爷 出品|产业家 熙熙攘攘的人群&#xff0c;琳琅满目年货&#xff0c;一张张喜庆的春联、福字、窗花……

零基础备考PMP,需要多长时间?

PMP是一门专业性很强的项目管理知识&#xff0c;考试当然是有一定的难度&#xff0c;但是也没有难到让你怀疑人生的程度。 如果你在学习PMP之前&#xff0c;已经有一些经验&#xff0c;那么备考一个半月基本上是没多大问题的&#xff0c;如果你是零基础小白&#xff0c;那么备…

2024全国水科技大会暨流域水环境治理与水生态修复论坛(六)

论坛召集人 冯慧娟 中国环境科学研究院流域中心研究员 刘 春 河北科技大学环境与工程学院院长、教授 一、会议背景 为深入贯彻“山水林田湖是一个生命共同体”的重要指示精神&#xff0c;大力实施生态优先绿色发展战略&#xff0c;积极践行人、水、自然和谐共生理念&…

基于RK3399 Android11适配OV13850 MIPI摄像头

目录 1、原理图分析2、编写和配置设备树3、调试方法4、遇到的问题与解决5、补丁 1、原理图分析 从上图可看出&#xff0c;我们需要关心的&#xff0c;①MIPI数据和时钟接口使用的是MIPI_TX1/RX1 ②I2C使用的是I2C4总线 ③RST复位引脚使用的是GPIO2_D2 ④PWDN使用的是GPIO1_C7 ⑤…

洛谷 【算法1-6】二分查找与二分答案

【算法1-6】二分查找与二分答案 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 鄙人不才&#xff0c;刷洛谷&#xff0c;迎蓝桥&#xff0c;【算法1-6】二分查找与二分答案 已刷&#xff0c;现将 AC 代码献上&#xff0c;望有助于各位 P2249 【深基13.例1】查找 - 洛谷…

MySQL数据库基础(十三):关系型数据库三范式介绍

文章目录 关系型数据库三范式介绍 一、什么是三范式 二、数据冗余 三、范式的划分 四、一范式 五、二范式 六、三范式 七、总结 关系型数据库三范式介绍 一、什么是三范式 设计关系数据库时&#xff0c;遵从不同的规范要求&#xff0c;设计出合理的关系型数据库&…

Clickhouse系列之连接工具连接、数据类型和数据库

基本操作 一、使用连接工具连接二、数据类型1、数字类型IntFloatDecimal 2、字符串类型StringFixedStringUUID 3、时间类型DateTimeDateTime64Date 4、复合类型ArrayEnum 5、特殊类型Nullable 三、数据库 一、使用连接工具连接 上一篇介绍了clickhouse的命令行登录&#xff0c…

数字滚动实现

介绍 vue-countup-v3 插件是一个基于 Vue3 的数字动画插件&#xff0c;用于在网站或应用程序中创建带有数字动画效果的计数器。通过该插件&#xff0c;我们可以轻松地实现数字的递增或递减动画&#xff0c;并自定义其样式和动画效果。该插件可以用于许多场景&#xff0c;例如展…

ELK介绍以及搭建

基础环境 hostnamectl set-hostname els01 hostnamectl set-hostname els02 hostnamectl set-hostname els03 hostnamectl set-hostname kbased -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config systemctl stop firewalld & systemctl disable firewalld# 安…

pytest结合Allure生成测试报告

文章目录 1.Allure配置安装2.使用基本命令报告美化1.**前置条件**2.**用例步骤****3.标题和描述****4.用例优先级**3.进阶用法allure+parametrize参数化parametrize+idsparametrize+@allure.title()4.动态化参数5.环境信息**方式一****方式二**6.用例失败截图1.Allure配置安装 …

【深度学习】微调通义千问模型:LoRA 方法,微调Qwen1.8B教程,实践

官网资料: https://github.com/QwenLM/Qwen/blob/main/README_CN.md 文章目录 准备数据运行微调设置网络代理启动容器执行 LoRA 微调修改 finetune/finetune_lora_single_gpu.sh运行微调 执行推理 在本篇博客中&#xff0c;我们将介绍如何使用 LoRA 方法微调通义千问模型&#…