一篇文章了解区分指针数组,数组指针,函数指针,链表。

最近在学习指针,发现指针有这许多的知识,其中的奥妙还很多,需要学习的也很多,今天那我就将标题中的有关指针知识,即指针数组数组指针函数指针,给捋清楚这些知识点,区分这些名词,望各位能赏眼观看一下,如有不足,还请指点。下面就开始敲下这篇文章了。

目录

指针数组

 数组指针

函数指针

链表


指针数组

指针数组,那么何为指针数组?仅仅看这个名词,各位觉得它是数组还是指针变量呢?那我们先来看一下官方的解释,何为指针数组。 

在 C 语言中,指针数组是一种特殊的数据结构,它是一个数组,其中每个元素都是一个指针。
 

指针数组的定义方式如下:
 
类型 *数组名[数组大小];
 
 
其中, 类型  是指针所指向的元素的类型, 数组名  是指针数组的名称, 数组大小  表示指针数组的大小。
 
例如,以下代码定义了一个整数指针数组:
 
 

int *ptrArray[10];


 
这个指针数组  ptrArray  可以存储 10 个指向整数的指针。
 
指针数组的成员可以像普通指针一样进行操作,可以通过指针间接访问所指向的元素。例如:
 

int num = 10;
ptrArray[0] = #


 
 
上述代码将整数变量  num  的地址赋值给指针数组  ptrArray  的第一个元素。
 

需要注意的是,指针数组中的每个指针都需要单独进行内存分配和释放,确保在使用指针数组时正确管理内存。

指针数组的概念我们已经了解得差不多了,那么我们也实际运用一下指针数组吧!

运用指针数组来模拟出一个二维数组

相信各位那么聪明也是很快就想出怎么敲出这个简单的代码了吧。下面展示本人的代码。如下:

int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 11,22,33,44,55 };int arr3[5] = { 6,7,8,9,10 };int* p[3] = { &arr1,&arr2,&arr3 };int i = 0;int j = 0;for (i = 0; i < 3; i++){for (j = 0; j < 5; j++){printf("%d ", p[i][j]);}printf("\n");}return 0;
}


根据运行结果来看,代码是完美的运行成功了。

需要注意的是:这里虽然是好像 *p[ 3] 确实可以完成一个二维数组的功能,但也是和真正的二维数组有所区别的,二维数组中的相邻元素中的地址也是连续的,而用指针数组模拟出来的每个元素地址,并不是连续的。大家可看下下面的图。

很明显3个数组的地址是不连续的,故里面的元素地址肯定也不是连续的。


 数组指针

数组指针,咋一看怎么和刚刚说的指针数组那么像呢?那数组指针是指针还是数组呢?老样子我们看看官方的回答。

在 C 语言中,数组指针是一个指向数组的指针。它用于通过指针访问和操作数组中的元素。
 
数组指针的定义方式如下:
 
 
类型 (*指针名)[数组大小];
 
 
其中, 类型  是数组元素的类型, 指针名  是数组指针的名称, 数组大小  表示数组的大小。
 
例如,以下代码定义了一个整数数组指针:
 
 

int (*ptrArray)[10];


 
 
这个数组指针  ptrArray  可以指向一个包含 10 个整数元素的数组。
 
使用数组指针,可以通过指针间接访问和操作数组中的元素。例如:
 
 

int arr[10] = {0};
ptrArray = &arr;


 
上述代码将整数数组  arr  的地址赋值给数组指针  ptrArray ,使得  ptrArray  指向  arr  数组。
 

通过  ptrArray  可以访问和操作  arr  数组中的元素,如下所示:
 
 

printf("%d\n", *ptrArray[0]);


 
上述代码使用间接寻址运算符  *  来访问数组指针  ptrArray  所指向的数组的第一个元素。
 

需要注意的是,在使用数组指针时,要确保指针所指向的数组的边界和指针的类型匹配,以避免越界访问和错误。
 
 


看完大家是不是又对这个知识有了更加透彻的理解了呢?

那看完了我们也用数组指针来实践应用到代码当中!

二维数组传参,数组指针来接收

在实践之前我们首先要知道一个知识点,我上篇文章说过,传参时如果用数组名进行传参,传过去的是数组的首元素大小,那么我们知道一维数组的首元素为数组的第一个值,那么二维数组呢?也是第一行第一个数吗?事实上二维数组的首元素其实是第一行,注意这里说的是整整一行,而不是一个,那么怎么证明呢?继续往下看。


#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{int arr[3][4] = { {1,2,3,4},{11,22,33,44},{7,8,9,10} };printf("%d\n", sizeof(*arr));         //首元素大小,也就是第一行元素的大小printf("%d\n", sizeof(*(arr+1)));           //第二行元素的大小return 0;
}

从结果上不难发现这里 显示的16,正是第一行的4个元素的大小。故其实二维数组的首元素为数组的第一行。

那么知道这个知识点之后我们就可以开始完成上面说的实际应用了,二维数组传参,数组指针来接收 。因为传的是第一行,那么我们不妨就用数组指针来接收。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>void Print(int(*p)[4], int x, int y)
{int i = 0;int j = 0;for (i = 0; i < x; i++){for (j = 0; j < y; j++){printf("%d ",(*(*(p + i) + j)));}printf("\n");}}int main()
{int arr[3][4] = { {1,2,3,4},{11,22,33,44},{7,8,9,10} };Print(arr, 3, 4);return 0;
}

在这串代码中,我们通过数组名将arr数组的首元素传到函数Print中,用数组指针p来接收,最后完成数组打印。

到这里我们先来一个小总结:指针数组就是存着指针的数组数组指针就是指向数组的指针,我们只需要抓住后面的名词即可区分住指针数组数组指针了。 


函数指针

”函数指针“,当初我刚学的时候也在想函数也有指针吗?直到学到这个知识点才逐渐明白。

那么什么是函数指针呢?老样子我们看一下官方的解释。

在 C 语言中,函数指针是一个指向函数的指针。它用于通过指针调用函数。
 
函数指针的定义方式如下:
 
 
返回值类型 (*函数指针名)(参数列表);
 
 
其中, 返回值类型  是函数返回值的类型, 函数指针名  是函数指针的名称, 参数列表  是函数的参数列表。
 
例如,以下代码定义了一个指向整数函数的指针:
 
 

int (*funcPtr)(int, int);


 
 
这个函数指针  funcPtr  可以指向一个返回整数并接受两个整数参数的函数。
 
使用函数指针,可以通过指针调用所指向的函数。例如:
 
 

int add(int a, int b)
{return a + b;
}funcPtr = add;


 
上述代码将函数  add  的地址赋值给函数指针  funcPtr 使得  funcPtr  指向  add  函数。
 
然后,可以使用  funcPtr  来调用  add  函数,如下所示:
 
 

int result = funcPtr(3, 4);


 
 
上述代码通过函数指针  funcPtr  调用了  add  函数,并将结果存储在变量  result  中。
 
使用函数指针可以实现函数的动态调用,使代码更加灵活和可复用。


看完上面的内容,相信各位对函数指针也有所了解了。

那我们在深入一点,回想当初我们调用函数时所用的都是数组名进行调用,那么这里我们就要思考一下了,函数的数组名是什么呢?

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>int Add(int a, int b)
{return a + b;
}int main()
{int (*p)(int, int) = &Add;printf("%p\n", p);printf("%p\n", Add);int c=(*p)(3, 4);int d = p(3, 4);int f = Add(3, 4);printf("c=%d\n", c);printf("d=%d\n", d);printf("f=%d\n", f);return 0;
}


 

观察上面代码,是否发现数组名Add和指针p打印出来都是同一个地址,说明其实数组名也是一个地址,而且我上面的代码运用了三种方法去调用这个函数,可以发现调用时即使是指针也不一定要用”*“。

了解完后想必大家都在想那函数指针有什么用呢?数组名就可以调用函数了,要指针来干嘛。这个就要涉及到链表函数回调了。


链表

 链表的话我们可以简单理解为函数指针数组,咋一听是不是又发现了一个新名词了。其实它也不是很难,可以参考指针数组,函数指针数组多了两字,也就是储存函数指针的数组,这么一听是不是又对它明了许多呢。

函数指针数组定义如下:

返回值类型 (*函数指针名)[数组个数](参数列表);

举例如下:

int (*p)[10](int ,int)

下面是一个用链表的应用完成一个计算器功能:

#include <stdio.h>
int Add(int a, int b)
{return a + b;
}
int Sub(int a, int b)
{return a - b;
}
int Mul(int a, int b)
{return a * b;
}
int Div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;int(*p[5])(int x, int y) = { 0, Add, Sub, Mul, Div };do{printf("*************************\n");printf(" 1:加法   2:减法 \n");printf(" 3:乘法   4:除法 \n");printf(" 0:退出 \n");printf("*************************\n");printf("请选择你所需的功能:");scanf("%d", &input);if ((input <= 4 && input >= 1)){printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = (*p[input])(x, y);printf("ret = %d\n", ret);}else if (input == 0){printf("退出计算器\n");}else{printf("输⼊有误\n");}} while (input);return 0;
}

上面我们将运算的加减乘除函数写出来后,利用函数指针数组将其储存起来,然后根据用户选择的选项调用其数组的元素,也就是加减乘除的函数,最后通过指针进行调用,完成功能。

这就是函数指针的实践运用了。至于函数回调,就要留到下一篇指针文章了。敬请期待哦!

文章已到末尾,望各位多多支持。

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

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

相关文章

深度解析Go字符串

Go语言中的字符串是一种不可变的字节序列&#xff0c;它在编程中扮演着重要的角色。接下来将深入探讨Go字符串的基本概念、常见操作、性能优化&#xff0c;以及最佳实践&#xff0c;旨在帮助大家更好地理解和利用Go语言中的字符串。 1. 字符串的基本概念 1.1 字符串的表示 在…

react native错误记录

第一次运行到安卓失败 Could not find implementation class com.facebook.react.ReactRootProjectPlugin for plugin com.facebook.react.rootproject specified in jar:file:/D:/Android_Studio_Data/.gradle/caches/jars-9/o_3a1fd35320f05989063e7069031b710f/react-nativ…

[碎碎念]全篇都是碎碎念,就不要点进来了~

去年九月份入职了新公司,本准备大干一场,结果没想到十一月公司被收购,随之而来的就是裁员 被裁之后索性就不打算找工作了,给自己一年的时间,去做点自己喜欢的事情 至于做什么还没想好,至于一年之后能不能做出来什么也不知道,一切都是不确定,一切都是未知 不过也正是如此,生活才…

综合布线技术(复习)

一、 我国在20世纪80年代末期开始引入综合布线系统&#xff0c;90年代中后期得到迅速发展 综合布线系统是建筑群或建筑物内的传输网络系统&#xff0c;他能使语音和数据通信设备、交换设备和其他信息管理系统彼此相连接 综合布线系统国家标准主要有&#xff1a;GB 5031-2016…

LabVIEW智能温度直流模件自动测试系统

LabVIEW智能温度直流模件自动测试系统 自动化测试系统在提高测试效率和准确性方面发挥着越来越重要的作用。介绍了一种基于LabVIEW的智能温度直流模件&#xff08;TDCA&#xff09;自动测试系统的设计与实施&#xff0c;旨在提高测控装置的产品质量。 系统的硬件平台主要由PS…

一篇文章搞懂CNN(卷积神经网络)及其所含概念

目录 1. 什么是卷积神经网络&#xff1a;2. 应用领域&#xff1a;3. 架构&#xff1a;4. 卷积层的参数和名词参数&#xff1a;名词&#xff1a; 5. 注意&#xff1a;6. 经典网络&#xff1a;小结&#xff1a; 当下&#xff0c;计算机视觉在人工智能领域中扮演着至关重要的角色。…

unity 使用数字图片来代替数字0到9显示

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Trackracecomplete : MonoBehaviour { /// /// 数字图片 /// [SerializeField] private Sprite[] sprites; private string _Time “23:57:49”; [Ser…

matlab使用jdbc连接数据库

1、打包jdbc 2、在matlab安装目录下&#xff0c;进去toolbox目录下&#xff0c;新建一个对应放jdbc包的文件夹&#xff0c;加入放入的是mysql的jdbc驱动包&#xff0c;就新建一个mysql目录&#xff0c;将驱动包放入mysql目录下 3、在toolbox目录下&#xff0c;找到local目录&a…

手工方式安装19.22RU

使用手工方式打RU19.22 参考文档&#xff1a; Supplemental Readme - Grid Infrastructure Release Update 12.2.0.1.x / 18c /19c (Doc ID 2246888.1) 操作步骤&#xff1a; 1 Stop the CRS managed resources running from DB homes. 2 Run the pre root script. 3 Patch G…

C语言问题汇总

指针 #include <stdio.h>int main(void){int a[4] {1,2,3,4};int *p &a1;int *p1 a1;printf("%#x,%#x",p[-1],*p1);} 以上代码中存在错误。 int *p &a1; 错误1&#xff1a;取a数组的地址&#xff0c;然后1&#xff0c;即指针跳过int [4]大小的字节…

【Golang】exec.command命令日志输出示例

背景 为了输出执行命令的日志&#xff0c;主要是执行时间很长&#xff0c;而且分批输出日志的命令。 代码 func Execute(){command : exec.Command("执行命令")// 隐藏黑色窗口command.SysProcAttr &syscall.SysProcAttr{CreationFlags: 0x08000000}// 输出日…

debian10 / deepin20.9 vim安装leaderf插件

首先&#xff0c; 自带的vim是不支持python的&#xff0c;安装vim-nox apt install vim-nox 安装python3的依赖库&#xff0c; 不安装的话&#xff0c;leaderf安装扩张会报错 sudo apt-get install build-essential python3-dev libssl-dev libffi-dev libxml2 libxml2-dev …

SQL 函数(十二)

SQL 函数&#xff08;十二&#xff09; 一、函数分类 1.1 单行函数 单行函数仅对单个行进行运算&#xff0c;并且每行返回一个结果。 常见的函数类型&#xff1a; 字符、数字、日期、转换 1.2 多行函数 多行函数能够操纵成组的行&#xff0c;每个行组给出一个结果&#x…

创新大赛专访丨南沙人才荣膺2023年度人才寻猎标杆品牌:吸纳海内外高学历人才,助力南沙精准“选苗”

日前&#xff0c;2023第三届全国人力资源创新大赛颁奖典礼暨成果展圆满举行。自2023年10月份启动以来&#xff0c;大赛共吸引了457个案例报名参赛&#xff0c;经组委会专家团队评审严格审核&#xff0c;企业赛道共有103个案例获奖、72家企业、13位个人、7个产业园斩获荣誉。 广…

Unity引擎学习笔记之【角色按键器操作】

角色按键Character Controls 一、脚本操作 设置脚本 设置基本键盘操作 //水平轴float horizontal Input.GetAxis("Horizontal");//垂直轴float vertical Input.GetAxis("Vertical");//创建方向向量Vector3 dir new Vector3(horizontal,0,vertical);/…

maven在setting配置文件中指定jdk为1.8版本

setting.xml修改如下配置&#xff1a; <profile><id>jdk-1.4</id><activation><jdk>1.4</jdk></activation><repositories><repository><id>jdk14</id><name>Repository for JDK 1.4 builds</name…

Unity根据落点和抛物线运行时间,求初始力

抛物线运行时长为2秒&#xff1a; 抛物线运行时长为4秒&#xff1a; 原理就是&#xff1a; 在竖直方向只受重力&#xff0c;做匀加速直线运动&#xff0c;水平不受力&#xff0c;做匀速直线运动。 代码&#xff1a; public void Update(){if (Input.GetKeyDown(KeyCode.Space)…

《Python 网络爬虫简易速速上手小册》第2章:网络爬虫准备工作(2024 最新版)

文章目录 2.1 选择合适的爬虫工具和库2.1.1 重点基础知识讲解2.1.2 重点案例&#xff1a;使用 Scrapy 抓取电商网站2.1.3 拓展案例 1&#xff1a;使用 Requests 和 BeautifulSoup 抓取博客文章2.1.4 拓展案例 2&#xff1a;使用 Selenium 抓取动态内容 2.2 设置开发环境2.2.1 重…

新增!该地发放「软考电子证书」,赶快下载打印!

近日&#xff0c;浙江省科技宣传教育中心发布《关于2023年下半年全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;浙江考区&#xff09;电子合格证明下载打印的通知》&#xff0c;浙江省2023年下半年全国计算机技术与软件专业技术资格&#xff0…

Linux 网络编程 + 笔记

协议&#xff1a;一组规则 分层模型结构&#xff1a; OSI七层模型&#xff1a;物理层、数据链路层、网络层、传输层、会话层、表示层、应用层TCP/IP 4层模型&#xff1a;链路层/网络接口层、网络层、传输层、应用层 应用层&#xff1a;http、ftp、nfs、ssh、telnet、传输层&am…