C/C++相关概念和易错知识点(11)(二级指针、数组指针、函数指针)

C/C++指针进阶:数组指针、函数指针、二级指针与智能指针全解析 内存地址是理解编程底层机制的基础概念,指针作为保存地址的变量,在C/C++中承担着操作内存、传递数据的重要职责。围绕指针衍生出的组合形态,让许多学习者头疼:指针数组与数组指针如何区分?函数指针怎么用于回调?二级指针为什么能在链表中修改头结点?野指针又是如何产生并导致崩溃的?这些问题都与指针的声明规则、步长语义及资源所有权密切相关。C++中引入的智能指针则通过RAII机制自动管理堆内存,有效避免手动释放带来的内存泄漏与悬空指针风险。从基本的数组遍历到多维数组传参、链表操作等工程场景,系统掌握指针的知识体系,有 阅读详情

指针在C语言中非常关键,除开一些常见的指针用法,还有一些可能会比较生疏,但有时却也必不可少,本文章整理了一些易错知识点,希望能有所帮助!

1.二级指针:

2ab567f99dc74a5fb7c598652e9fe23a.png

parr是一个指针数组,其中每个元素存储字符串首字符的地址

d120d1e5c04f4abb89f9e27ac31d35c2.png

parr在这里表示首元素的地址,首元素是"Hello!"的'H'的地址,所以parr表示的是'H'的地址的地址,用char**来存储,如果解引用p就得到'H'的地址,相当于parr[0]。

如果使用p + 1,就会跳过一个char*的大小,在这里是8个字节(64位平台)。要理解p的加法含义,我们需要知道内存中的每一个字节都有一个地址,这个地址相当于内存的标签,它指向我们存储的内存空间,存储该数据需要k个字节,那么这些地址的数值差也是k。

83d0070198314e248fdfc435a742380e.png

以上面的例子讲解:p对应的是首元素地址,相当于一块内存空间的标签,在p这个地址下存储char*的具体值,占了8个字节。p + 1就会找到紧接着第一个char*的下一个char*存储的内存空间的地址。p + 2同理。

0ea1c3841d1048c09ac906b4f6733734.png

139c85e5aa354b77b3e3a2e33c152b3f.png

我们可以通过这两张图看到,地址是内存空间的标签,在内存里存储数据,地址则是负责找到这块空间。理解了这里,那么指针的大部分问题都会解决。

2.一维数组指针:

注意数组指针的本质是指针,它存储的值是数组的首元素地址,象征着它指向的对象是一个数组。但是,很多人会注意到,既然存储的值和单独取首元素地址的指针存储的值相同,那么怎么区分它们?

区分它们的主要方式有以下几点:首先,指针+1跳过的大小不同,数组指针+1会跳过数组的大小,而单独取首元素地址对应的指针+1只会跳过该元素的大小。

8c52e215b4624fd294502abea2e4ab79.png

这里可以轻松算出两者之间相差32,即一个数组的大小。

4a8894914f814dfea961cb2c3adb03ad.png

注意:arr单独表示整个数组,而arr + 0 表示第一个元素地址,两者有本质区别

那么,既然两者存储的值相同,那么它们之间在除强制转换这种方法以外是否有其它转换方法?

我们知道,数组指针是对整个数组取地址,即&arr,假设这个指针表示为int (*parr) [10] = &arr,那么*parr得到的就是*(&arr)即arr,相当于首元素地址,也就是int*,所以首元素的地址也可表示为int* p = *parr。

0e73932029b74d9db407556b8bede88a.png

我们要尝试理解它的本质,不要死记硬背,学会分析会帮助我们更好的运用指针。

下面四种写法均等效:

949540125c69469b86e97d25bb34fe20.png

3.二维数组指针:

二维数组指针是一维数组指针的变形,理解了一维数组的指针,二维数组指针就可以轻松应对了。

首先熟悉一下二维数组的初始化过程:

9b0597c523454b3faf88812f898c28bd.png

其中arr[2][2]中第一个2代表2行,第二个2代表2列。

下面是有关二维数组指针易混的代码,可以尝试解释:

3a28f0ca98a045888e8938b642094d3f.png

对数组的解释具体如下图:

c068952634884c6c8526baeec6c8b07a.png

理解了这里,那么二维数组就基本掌握了,下面看看整型数组指针和整型指针的转换,加深理解:

0c57b28c28cb4c2aa6541613543df0cb.png

说到底,二维数组就是将一维数组作为元素存储在数组中,刚开始会觉得有点绕,不过多看几遍就能很好理解运用了。

注意二维数组传参:

490e53c332fa4f7ea7e8bd0ed5a19ece.png

这里arr传的是首元素(数组)地址,要用数组指针来接收,数组指针传参不能省略元素个数

57af2f1f9eb64a1ebc7c24a8aabd0a07.png

667a356193724d4d8445b19fc9a681da.png

二维数组在函数内取值要注意层级:

a10cd18a5d4f49809fc5f6599a69fc63.png

&arr是对整个arr取地址,是二维数组的指针,第一次解引用得到arr,首元素(数组)的地址,即一维数组指针,第二次解引用是对元素数组解引用,得到首元素(整型)的地址(注意理解)即int*,第三次解引用就能得到值。

4.函数指针:

函数指针一般用的不多,但是我们要清楚它的用法。对于int Fun (int a, int b),其对应的函数指针应表示为int (*pFun) (int a, int b) = Fun,当然也可写作&Fun。使用过程中,可以直接将pFun当作函数名一样使用,如pFun (1, 2)。多个函数指针也可以组成一个数组,成为函数指针数组,如int (*pFunarr[2]) (int a, int b) = { pFun1, pFun2 };它可以用于传递参数相同,且实现的功能有相似度的几种函数的集合,如加减乘除的函数的集合。


#include <stdio.h>

int add(int x, int y)
{
	return x + y;
}

int sub(int x, int y)
{
	return x - y;
}

int mul(int x, int y)
{
	return x * y;
}

int div(int x, int y)
{
	return x / y;
}

int main()
{
	int (*pFun[4]) (int x, int y) = { add, sub, mul, div };

	printf("%d\n%d\n%d\n%d", pFun[0](1, 1), pFun[1](1, 1), pFun[2](2, 3), pFun[3](8, 2));

	return 0;
}

36ce2c7dcc2d4cbcb9dc82b5376469ac.png

注意函数指针和函数指针数组传参:

b3980b27ea2a440e94dc322a41921936.png

 注意因为函数指针创建可以&fun也可直接fun,在解引用时也可选择加*或不加*

556582ccbe8d48edb81e9413dc025be6.png

但是要注意层级不要弄错:

912358fb88614f0b934b8748fad7e08f.png

这里是函数指针的指针,pFun + 1相当于找到了存储减法函数地址的地址,但是只有在减法函数地址这个层级才能使用。

MATLAB实战:手把手教你实现Gardner环路位同步(附完整代码) 本文通过MATLAB实战,详细讲解了Gardner环路位同步算法的原理与实现。内容涵盖插值滤波器、定时误差检测、环路滤波器与数控振荡器等核心模块,并提供完整代码和调试技巧,帮助读者掌握数字通信中关键的符号定时同步技术。 阅读详情

相关推荐

Unity2D像素刀光实现:粒子方向控制与像素级渲染规范

像素风游戏中的刀光特效并非普通粒子动画,而是需严格遵循像素艺术原理的视觉暂留模拟。其核心在于将‘瞬时切割感’转化为程序可执行的渲染逻辑:通过禁用纹理滤波保障1:1像素锐度,绑定刀锋向量控制粒子运动方向,限定≤0.15秒生命周期匹配人眼暂留阈值,并采用Stretched Billboard实现动态拉伸拖影。该方案兼顾美术语义(如直劈、横扫、突刺)与工程约束(Sorting Layer分层、对象池复用、单粒子GPU优化),广泛适用于Unity2D平台的动作反馈系统,尤其适配《空洞骑士》《死亡细胞》类高节奏像素R

weixin_32390647的博客 282

指针详解2:二级指针与指针数组

二级指针,顾名思义,是个二次的指针,也就是指向指针的指针 基本类型如下: int** p; 我们来看一段代码: void d_pointer() { int a = 10; int* pa = &a;//pa是一个指针变量,变量有地址,所以有&pa int** ppa = &pa; //ppa就是一个二级指针 第二颗星是说这是一个指针,第一个是说指针的对象是一个指针 //int*** pppa = &ppa 三级指针 printf("\n"); print

awaitxm的博客 3021

手把手教你用CANopen SDO报文控制步进电机(附CIA402协议详解)

本文详细解析了如何通过CANopen SDO报文控制步进电机,深入讲解CIA402协议的核心架构、状态机模型及对象字典管理,并提供实战代码示例。从SDO报文构造到多轴同步控制,帮助开发者掌握工业级步进电机的精确控制技术,适用于自动化设备开发。

weixin_33737774的博客 485

【C语言】函数指针和指针函数

今天学一下函数指针提示:以下是本篇文章正文内容,下面案例可供参考函数指针:是一个指向函数的指针,在内存空间中存放的是函数的地址。parr是一个指向数组的指针,它存放的是数组的地址数组指针–存放数组地址的指针&数组名–得到数组地址==函数指针–存放函数地址的指针&函数名–得到函数地址函数指针的本质是一个指针,该指针的地址指向了一个函数,所以它是指向函数的指针。函数指针:函数的返回值类型(*指针名)(函数的参数列表类型)

weixin_61196797的博客 783

使用STM32制作简易数字时钟

连接LED数码管的电源和地线到STM32单片机的对应引脚,将数码管的A、B、C、D引脚连接到STM32单片机的I/O口引脚。通过编写和调试这个项目,可以熟悉STM32单片机的GPIO口和定时器的使用,以及数字显示的控制。步骤六:测试和调试 通过观察数码管的显示,可以验证时钟功能是否正常工作。步骤四:编写代码 在主程序中,我们将使用定时器中断来控制时钟的运行,并使用GPIO口控制LED数码管的显示。步骤五:编译和下载 编译代码并下载到STM32单片机中,通过调试器和串口监视器进行调试和查看输出结果。

qq_67153941的博客 1302

保姆级教程:用BIGEMAP和Global Mapper搞定5米精度DEM高程数据下载与处理

本文提供了一份详细的5米精度DEM高程数据处理教程,涵盖从BIGEMAP下载到Global Mapper处理的完整流程。通过实战案例和避坑指南,帮助用户掌握高效下载DEM数据、优化等高线生成及坐标系转换的关键技巧,适用于GIS新手和专业人士。

weixin_34169322的博客 390

指针详解(二级指针、指针数组和数组指针、字符指针、二维数组传参、函数指针变量)(二)

1、 (*(void (*)())0)(); 2、void (*signal(int , void(*)(int)))(int); 1、为什么一维数组传参,形参可以是数组,也可以是指针? 1.写成数组更加直观,为了方便理解 2.写成指针传参是因为数组传参,传递的是数组的第一个元素的地址 二维数组传参,形参写成数组也是可以的,非常直观,容易理解 2、形参能写成指针吗? 可以,用数组指针 二维数组其实就是元素是一维数组的数组 数组名就是数组首元素的地址 首元素的地址就是第一行的地址

走在努力路上的自己的博客 1194

零基础实战:YOLO检测头自定义替换全攻略

本文为零基础用户提供了YOLO检测头自定义替换的完整实战指南。通过将检测头比作汽车的“方向盘”,文章详细阐述了为何需要替换、如何寻找和集成新检测头模块、修改配置文件以及最终训练验证的全过程,旨在帮助用户针对特定任务(如小目标检测)提升模型性能。

perl8的博客 255

深入理解C语言指针的奥秘[转]

 http://topic.youkuaiyun.com/u/20070112/09/35186e5a-0d94-4ea6-9b72-c5463cb3d1f3.html指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。   要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的   类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。     先

hdccd的专栏 605

蓝牙耳机充电仓——功能框架

数据传输:大部分充电仓会跟耳机通信,控制耳机开机、关机和进入可搜索模式等等。蓝牙耳机给大家的生活带来便利,来讲讲TWS蓝牙耳机的搭档充电仓吧!方便携带:如果耳机单独带着,指定能弄丢一个,有了充电仓就安全多了。收纳保护:把珍爱的耳机放入充电仓里,防止丢失、磕碰、刮花等。给耳机充电:提供电力补给,让耳机持续使用。

改变自己现在能改变的,珍惜自己现在所拥有的 8948

Android Binder——数据传递载体(二十一)

同一进程间的对象传递都是通过引用来做的,因而本质上就是传递了一个内存地址。而跨进程采用了虚拟内存机制,两个进程都有自己独立的内存地址空间,所以跨进程传递的地址值是无效的。进程间的数据传递是 Binder 机制中的重要一环,Android 系统中担负这一重任的就是 Parcel。Parcel 是一种数据的载体,用于承载希望通过 IBinder 发送的相关信息(包括数据和对象引用)。正是基于 Parcel 这种跨进程传输数据的能力,进程间的 IPC 通信才能更加平滑可靠。

小旭的专栏 576

C语言基础—指针(地址引用、指针数组、二次指针、多维数组指针、指针常量)

本章主要讲解指针的基本定义和指针的传递、偏移。后面继续讲解指针数组和多维指针、二级指针. 指针类型的总结 比如常量指针和变量指针. 区分指针常量和常量指针. 以及 多维指针, 比如指向多维数组的指针等 知识点: - 指针的定义和指针分类 - 各类指针的字节长度取决于系统位数 - 指针的传递(值传递和引用(地址传递)) - 指针的偏移(自增自减号) - 指针数组的应用 - 指针动态内存申请 - 字符指针和字符数组的初始化和易错点 - 易错点:指针变量指向常量区数据不可修改 - 二次指针&传递 - 指针/常量

Half-up的博客 1494

S7-1200中通过MODBUS TCP客户端在一次请求中实现从服务器读写一个或多个保持性寄存器的具体方法

S7-1200中通过MODBUS TCP客户端在一次请求中实现从服务器读写一个或多个保持性寄存器的具体方法

Robot_PLC_HMI_Automation 4225

C/C++:函数指针

要声明和初始化函数指针,首先需要知道要指向的函数的签名(返回类型和参数类型)。然后,你可以声明一个函数指针变量,并将其初始化为指向特定函数的地址。

2301_79181030的博客 1900

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

嵌入式知识点总结 C/C++ 专题提升(三)-指针

嵌入式知识点总结C/C++专题提升(三)-指针

你要拥有一个你喜欢并且热爱的人生 9256

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C/C++ 指针数组、数组指针、指针函数、函数指针详解

本文详细解析了C/C++中指针数组、数组指针、指针函数和函数指针的区别与应用。指针数组是存储指针的数组,常用于管理多个字符串;数组指针指向整个数组,适合处理二维数组。函数指针用于回调机制,而指针函数返回指针类型,多用于动态内存分配。通过语法定义、示例代码和对比表格,文章清晰区分了这些易混淆概念,并强调类型匹配和内存管理的重要性。掌握这些知识点对深入理解指针操作和高效编程至关重要。

本博客分享软硬件一体化开发实战。硬件涵盖 PCB 设计、STM32 等 MCU 底层开发;软件包含 C++、Rust,Qt/QML、PyQt、Slint、TouchGFX、LVGL 各类 GUI 框架。方便软硬件开发者查阅学习。欢迎关注! 1026

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

c/c++ 一级指针,二级指针,指针数组,数组指针,函数指针,指针函数

前言 学习c/c++的时候最让我们头疼的就是指针,各种类型的指针,各种概念,让我们看看什么是指针 正文 指针和内存息息相关 先让我们看看内存 这段内存大家都很熟悉 都知道数组名就是这个数组的首地址那我们怎么解读这块内存 分两块看这个内存 前边是内存的编号 后边是这个编号里面存的值 什么是内存的编号? 内存是连续的 一个接着一个 所以我们为了方便找到他们 给他们起了名字 也就是这块内存的地址 所以指针里面就是存了这些内存的编号 换句话说 指针存储了这块内存的地址 也就是指向了这块..

weixin_45012273的博客 449

函数指针声明、赋值、调用

一、函数指针声明 1、返回值类型 ( *指针变量名) ([形参列表]); ( *指针变量名) 函数指针声明时括号不能省略,否则改变了运算符的优先级,变成了返回一个指针的函数 ([形参列表])函数括号中的形参可有可无,视情况而定; 二、函数指针赋值 以下两种对函数指针的赋值哪个是正确的? int function(int a, int b) { //执行代码 } ...

清凉简装的博客 1万+

C/C++指针相关知识点总结(学不完,根本学不完!!!!)

指针是一个值为内存地址的变量(或数据对象)。首先指针是一个变量,它的值就是某个变量的内存地址,就好比 int 类型的变量它的值是整数也是一样的。//定义两个指针变量指向room int * p1 = & room;printf("room 地址:0x%p\n" , & room);printf("p1 地址:0x%p\n" , & p1);printf("p2 地址:0x%p\n" , & p2);printf("room 所占字节:%d\n" , izeof(room));

qq_42595610的博客 1493

【C/C++】庖丁解牛 指针的高端操作

在初阶c语言之浅识指针中,我已经详细地介绍了指针的概念:1.指针就是个变量,用来存放地址,地址唯一标识一块内存空间。2.指针的大小是固定的4/8个字节(32位平台/64位平台)。3.指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。4.指针的运算。接下来我们就进入指针的高阶主题继续深入的了解指针。

花想云的博客 1923

什么是 字符指针? 数组指针? 函数指针? 函数指针数组?

什么是字符指针, 函数指针, 数组指针, 函数指针数组, c语言刷题

酷酷学!!!的博客 1196

【转】嗯,让我们彻底搞懂C/C++函数指针吧

摘要:这篇文章详细介绍C/C++的函数指针,请先看以下几个主题:使用函数指针定义新的类型、使用函数指针作为参数、使用函数指针作为返回值、使用函数指针作为回调函数、使用函数指针数组,使用类的静态函数成员的函数指针、使用类的普通函数成员的指针、定义函数指针数组类型、使用函数指针实现后绑定以及在结构体中定义函数指针。如果您对以上这几个主题都很了解,那么恭喜您,这篇文章不适合您啦~。在一些开源软件中,如Bo

Dev-L的博客 5454

【C语言】指针进阶 - 指针数组 数组指针 数组指针传参 函数指针 指向函数指针数组的指针

目录 int main() { const str1[] = { "hello bit." }; const str2[] = { "hello bit." }; const char* str3 = "hello bit."; const char* str4 = "hello bit."; if (str1 == str2) //数组名 比较两个字符串首元素地址 printf("str1 and str2 are same\n"); else printf("str1 and s

1226 3872

C语言指针进阶:掌握数组指针、二维数组传参与函数指针

⼆维数组传参,形参的部分可以写成数组,也可以写成指针形式。

liugenwei的博客 1760

C/C++之回调函数与函数指针和类成员函数指针

函数指针 (1)概念:指针是一个变量,是用来指向内存地址的。一个程序运行时,所有和运行相关的物件都是需要加载到内存中,这就决定了程序运行时的任何物件都可以用指针来指向它。函数是存放在内存代码区域内的,它们同样有地址,因此同样可以用指针来存取函数,把这种指向函数入口地址的指针称为函数指针。 (2)先来看一个Hello World程序: int main(int argc,char* argv...

huang714的专栏 1696

C语言指针变量详解(函数指针,函数指针数组,转移表)

C语言指针学习中,函数指针,函数指针数组,转移表等等是非常迷惑的一部分,而本文章重点介绍C语言中指针与变量的关系和组合,包涵了各种常见的用法。看完本文章上面的疑惑自然也就有了答案。

zzz87的博客 1078
上一篇: C/C++相关概念和易错知识点(17)(堆、堆排序)
下一篇: C/C++相关概念和易错知识点(18)(二叉树、分治思想)
-SGlow-
博客等级 码龄3年 1513粉丝 118原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值