详解C语言指针的指针,不信你还不懂!!!

简介: 指针的指针(也叫二级指针)是 C 语言中很经典但也让人迷惑的一个知识点。下面我帮你用最详细、最通俗的方式来讲清楚它,保证你看完会豁然开朗!

C语言指针的指针详解(深入剖析)

一、什么是指针?

指针是一个变量,它存放另一个变量的地址。
例如:
int a = 10;
int *p = &a; // p 是指针,存放 a 的地址
php
43 Bytes
© 菜鸟-创作你的创作
二、指针的指针是什么?

指针的指针是一个指针变量,它存放的不是普通变量的地址,而是另一个指针变量的地址。
简单来说:

int p 是指向 int 类型的指针。
int **pp 是指向 int
类型指针的指针。
示意图:

a (int) = 10
p (int) ---------> a
pp (int*
) --------> p ---------> a
php
70 Bytes
© 菜鸟-创作你的创作
三、代码示例

include

int main() {
int a = 10;
int p = &a; // p指向a
int **pp = &p; // pp指向p
printf("a = %d\n", a);
printf("
p = %d\n", p); // 通过指针p访问a
printf("pp = %d\n", pp); // 通过指针的指针访问a
printf("a的地址 = %p\n", (void
)&a);
printf("p的值 (a的地址) = %p\n", (void)p);
printf("pp的值 (p的地址) = %p\n", (void
)pp);
printf("pp的值 (p的值,a的地址) = %p\n", (void)*pp);
return 0;
}
php
426 Bytes
© 菜鸟-创作你的创作
四、运行结果说明

a = 10
p = 10
**pp = 10
a的地址 = 0x7ffee2b8f9ac
p的值 (a的地址) = 0x7ffee2b8f9ac
pp的值 (p的地址) = 0x7ffee2b8f9a0
pp的值 (p的值,a的地址) = 0x7ffee2b8f9ac
php
137 Bytes
© 菜鸟-创作你的创作
p 保存 a 的地址。
pp 保存 p 的地址。
通过 **pp 访问 a。
五、为什么要用指针的指针?

多级数据结构操作:如动态二维数组、链表链表(链表的链表)等。
函数参数传递:要在函数内部修改指针本身,需要传递指针的指针。
六、函数中使用指针的指针修改指针

void allocate(int ptr) {
ptr = malloc(sizeof(int)); // 修改传入指针的指向
if (
ptr) {
ptr = 100; // 通过指针赋值
}
}
int main() {
int p = NULL;
allocate(&p);
printf("p指向的值: %d\n",
p);
free(p);
return 0;
}
php
250 Bytes
© 菜鸟-创作你的创作
传入的是 p 的地址(即 int **)。
在函数内部修改了 p 的值。
七、总结

术语 说明 举例
变量 存数据 int a = 10;
指针 存变量地址 int p = &a;
指针的指针 存指针变量的地址 int *
pp = &p;
八、画个图理解

+---------+ +----------+ +-----+
| pp | ----> | p | ----> | a |
+---------+ +----------+ +-----+
php
134 Bytes
© 菜鸟-创作你的创作
好嘞!接下来帮你详细讲解一下C语言中的三级指针、指针数组与数组指针的区别,以及C++中指针和引用的区别,让你彻底搞懂这些经常混淆的概念。

一、三级指针(指针的指针的指针)

  1. 定义与概念

三级指针是指向二级指针的指针,类型为 int *(举例)。
它保存的是二级指针变量的地址。
示意图:

变量 a (int)
指针 p (int ) ------> a
二级指针 pp (int ) ------> p
三级指针 ppp (int
) ------> pp
php
90 Bytes
© 菜鸟-创作你的创作

  1. 示例代码

include

int main() {
int a = 5;
int p = &a;
int pp = &p;
int
ppp = &pp;
printf("a = %d\n", a);
printf("p = %d\n", p);
printf("pp = %d\n", pp);
printf("ppp = %d\n", ppp);
return 0;
}
php
249 Bytes
© 菜鸟-创作你的创作

  1. 使用场景

需要操作多级指针时,如修改函数中传入的二级指针指向。
比如动态分配二维指针数组(多维指针)时,可能用到三级指针。
二、指针数组 vs 数组指针

  1. 指针数组(Array of pointers)

定义:数组的每个元素是一个指针。
示例:
int arr[3]; // 数组,包含3个 int 指针
php
32 Bytes
© 菜鸟-创作你的创作
用法:常用于存放字符串数组(字符指针数组)或多个变量的地址集合。
示例:

char *names[] = {"Tom", "Jerry", "Anna"};
printf("%s\n", names[1]); // 输出 Jerry
php
80 Bytes
© 菜鸟-创作你的创作

  1. 数组指针(Pointer to an array)

定义:指针指向一个数组。
示例:
int (*p)[3]; // 指向含3个int的数组的指针
php
31 Bytes
© 菜鸟-创作你的创作
用法:常用于指向多维数组的某一行。
示例:

int arr[2][3] = { {1,2,3}, {4,5,6}};
int (p)[3] = arr;
printf("%d\n", (
p)[1]); // 输出2,即第一行第二个元素
php
98 Bytes
© 菜鸟-创作你的创作

  1. 区别总结

特性 指针数组 数组指针
定义 数组的元素是指针 指向数组的指针
语法示例 int arr[3]; int (p)[3];
内存结构 连续存放指针 指向整个数组
访问示例 arr[0] 是一个指针 *p 是一个数组
应用场景 多指针集合 多维数组的行操作
三、C++ 指针与引用的区别

特性 指针 (Pointer) 引用 (Reference)
定义 存储变量地址的变量 变量的别名
声明方式 int p int &r
必须初始化 不必须(可为空指针) 必须初始化
可以修改指向 可以,指向不同变量 不能更改,始终引用初始变量
访问操作 需使用
解引用 直接使用,无需解引用
空指针安全 可以是 nullptr 不存在空引用(必须绑定)
语法灵活度 支持指针算术 不支持指针算术
使用场景 动态内存、数组、需要多次改变指向的情况 传递参数时避免复制、必须绑定变量
代码示例

int a = 10;
int b = 20;
int *p = &a; // 指针
int &r = a; // 引用
p = &b; // 指针可以改变指向
// r = b; // 引用不能改变指向,但会修改a的值为b
r = b; // 这里是修改a的值为20,不是改变引用指向
printf("a = %d, b = %d\n", a, b); // a=20, b=20
php
216 Bytes
© 菜鸟-创作你的创作
四、总结

知识点 关键理解
三级指针 指向二级指针的指针,多级间接访问变量
指针数组 元素是指针的数组,用于存放多个指针
数组指针 指向数组的指针,指向整个数组
C++ 指针和引用 指针可变指向,引用为变量别名,不可改变
明白!下面给你详细梳理这几个概念的内存示意图、复杂代码案例,以及C语言中函数指针的用法示范,帮你彻底理解。

一、内存示意图

  1. 三级指针内存示意

+----------+ +---------+ +-----+
| ppp | ---> | pp | ---> | p |
+----------+ +---------+ +-----+
|
v
+-----+
| a |
+-----+
php
338 Bytes
© 菜鸟-创作你的创作
ppp 存放 pp 的地址
pp 存放 p 的地址
p 存放 a 的地址
三级指针通过三次解引用访问变量 a

  1. 指针数组 vs 数组指针内存示意

指针数组 int arr[3]
+----+----+----+
| p1 | p2 | p3 |
+----+----+----+
| | |
v v v
a1 a2 a3
数组指针 int (
p)[3]
+----------------------+
| a1 a2 a3 (array) |
+----------------------+
^
|
p
php
241 Bytes
© 菜鸟-创作你的创作
指针数组是数组,元素是指针
数组指针是指向整个数组的指针
二、复杂代码案例讲解

  1. 三级指针修改二级指针示例

include

include

void allocate(int ppp) { ppp = malloc(sizeof(int*)); // 分配一级指针空间 ppp = malloc(sizeof(int)); // 分配int空间
*ppp = 42; // 赋值
}
int main() {
int
pp = NULL;
allocate(&pp);
printf("value = %d\n", *pp);
free(
pp);
free(pp);
return 0;
}
php
339 Bytes
© 菜鸟-创作你的创作

  1. 指针数组遍历示例

include

int main() {
char *names[] = {"Tom", "Jerry", "Anna"};
int n = sizeof(names) / sizeof(names[0]);
for(int i = 0; i < n; i++) {
printf("%s\n", names[i]);
}
return 0;
}
php
214 Bytes
© 菜鸟-创作你的创作

  1. 数组指针访问多维数组示例

include

int main() {
int arr[2][3] = { {1,2,3}, {4,5,6}};
int (*p)[3] = arr;
for(int i = 0; i < 2; i++) {
for(int j = 0; j < 3; j++) {
printf("%d ", p[i][j]);
}
printf("\n");
}
return 0;
}
php
256 Bytes
© 菜鸟-创作你的创作
三、C语言函数指针详解与示范

  1. 函数指针定义

// 定义一个函数,参数两个int,返回int
int add(int a, int b) {
return a + b;
}
// 定义函数指针类型
int (*func_ptr)(int, int) = add;
php
113 Bytes
© 菜鸟-创作你的创作

  1. 使用函数指针调用函数

include

int add(int a, int b) {
return a + b;
}
int main() {
int (*func_ptr)(int, int) = add;
int result = func_ptr(3, 4);
printf("result = %d\n", result); // 输出 7
return 0;
}
php
208 Bytes
© 菜鸟-创作你的创作

  1. 函数指针作为参数传递

include

int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a b; }
void compute(int x, int y, int (
op)(int, int)) {
printf("result = %d\n", op(x, y));
}
int main() {
compute(3, 4, add); // result = 7
compute(3, 4, mul); // result = 12
return 0;
}
php
300 Bytes
© 菜鸟-创作你的创作

  1. 指向函数指针的指针(函数指针的指针)

include

int add(int a, int b) { return a + b; }
int main() {
int (func_ptr)(int,int) = add;
int (*pp_func)(int,int) = &func_ptr;
printf("result = %d\n", (
pp_func)(3,4)); // 7
return 0;
}
php
221 Bytes
© 菜鸟-创作你的创作
四、总结

知识点 作用与示范
三级指针 操作多级指针变量,常用于动态分配多维指针
指针数组 管理多个指针,方便存放字符串等
数组指针 操作多维数组,指向数组整体
函数指针 变量存函数地址,实现回调、策略模式
函数指针的指针 指向函数指针变量,复杂场景或API封装使用
太棒了!下面我给你设计一个思路清晰的动态交互动画描述方案,帮助你直观理解这些复杂指针和函数指针的概念。如果你用工具(比如在线动画制作、PPT动画或者程序绘图)制作,这个思路会很实用。

动态交互动画设计方案

一、三级指针动态动画

动画内容:

显示变量 a(值:10)在内存中的位置,画一个框标注地址。
显示指针 p 指向 a,用箭头连线,标出 p 中存的地址。
显示指针的指针 pp 指向 p,再用箭头连线。
显示三级指针 ppp 指向 pp,画出三级箭头链。
演示通过 *ppp 访问 a,每点击一次高亮对应一层解引用。
二、指针数组与数组指针对比动画

动画内容:

指针数组
画一排方框表示数组元素,每个元素存放一个指针地址。
箭头从每个元素指向不同变量(如字符串常量)。
演示访问 arr[0] 取得指针,再访问指针指向的内容。
数组指针
画一个指针指向一个连续的数组块。
演示通过 (*p)[index] 访问数组元素。
用颜色区分数组整体和指针变量。
三、函数指针与函数指针的指针动画

动画内容:

函数与函数指针
画一个函数代码块,标记函数地址。
画一个变量指针存储函数地址。
点击箭头演示用函数指针调用函数。
函数指针作为参数
画一个调用链,传入函数指针变量,调用不同函数示例。
函数指针的指针
画函数指针变量地址指针,形成多级箭头。
演示多级解引用调用函数。
四、交互设计建议

点击高亮指针或变量,显示它的类型和值。
箭头动态伸缩,显示指向关系。
步骤播放与暂停,方便理解每一步。
附带简短注释,解释当前操作含义。
五、实现工具推荐

PowerPoint / Keynote:使用形状、动画和触发器。
在线动画工具:如 Animaker 或 Canva 动画。
编程实现:用 JavaScript + SVG/Canvas(例如用 D3.js 或 p5.js)制作动态交互演示。
好的!下面给你一个基于HTML + JavaScript + SVG的简易交互动画示例代码,演示三级指针的动态解引用过程,帮你直观理解指针指向关系和多级解引用。

HTML + JS + SVG 动态三级指针示意动画示例

<!DOCTYPE html>


三级指针(int *ppp)动态解引用演示




a=10
地址:0x100


p
值:0x100


pp
值:0x200


ppp
值:0x200

















php
3.64 KB
© 菜鸟-创作你的创作
使用说明

打开此文件即可看到内存变量和指针示意框。
点击按钮逐步“解引用”三级指针,每一步都会高亮对应指针或变量,并显示说明。
方便你理解 ppp -> pp -> p -> a 的指向关系和多级解引用。
https://www.52runoob.com/archives/5393

相关文章
第一章MCS-51单片机结构,单片机原理、接口及应用
第一章MCS-51单片机结构,单片机原理、接口及应用
第一章MCS-51单片机结构,单片机原理、接口及应用
|
物联网 测试技术 网络性能优化
MQTT常见问题之收不到MQTT消息如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
监控 Windows
如何追踪Windows 进程自动异常退出
教你如何追踪Windows 进程自动异常退出
如何追踪Windows 进程自动异常退出
|
7月前
|
机器学习/深度学习 人工智能 PyTorch
三周内转型AI工程师学习计划
3周AI转型计划:掌握数学、机器学习与深度学习基础,熟练使用Python、PyTorch/TensorFlow。完成2-3个CV/NLP项目,构建GitHub博客,强化LeetCode刷题与模拟面试。每日高效学习9小时,聚焦实战与面试准备,助力快速入行AI。
608 0
|
7月前
|
存储 安全 算法
掌握C/C++中常见的加解密技术
在实现任何安全敏感功能时,务必要详尽地测试你的代码以确保其不仅能正常工作,并且能抵御常见的攻击方式,例如重放攻击、中间人攻击等。这种测试通常需要具备专业的安全知识,并且要检查一系列的安全性能指标。
352 0
|
数据安全/隐私保护 Windows
LabVIEW项目中使用库
LabVIEW项目中使用库
392 1
|
机器学习/深度学习 人工智能 监控
AI视频监控在大型商场的智能技术方案
该方案通过目标检测与姿态识别技术(如YOLO、OpenPose),实时监控顾客行为,识别异常动作如夹带物品、藏匿商品等,并结合AI模型分析行为模式,防止偷窃。出口处设置结算验证系统,比对结算记录与视频信息,确保商品全部支付。多角度摄像头和数据交叉验证减少误报,注重隐私保护,提升安保效率,降低损失率,增强顾客信任。
860 15
|
11月前
|
网络协议 数据安全/隐私保护 网络架构
|
程序员 编译器 C语言
C中的 malloc 和C++中的 new 有什么区别
在C语言中,`malloc`函数用于在运行时分配内存,返回指向所分配内存的指针,需显式包含头文件 `&lt;stdlib.h&gt;`。而在C++中,`new`不仅分配内存,还对其进行构造初始化,且直接使用类型声明即可,无需额外包含头文件。`new`还支持数组初始化,能更好地融入C++的面向对象特性,而`malloc`仅作为内存分配工具。使用完毕后,`free`和`delete`分别用于释放`malloc`和`new`分配的内存。
516 21