C语言指针专题四 -- 多级指针
目录
1. 多级指针的核心原理
1. 多级指针的定义
2. 内存结构示意图
3. 多级指针的用途
2. 编程实例
实例1:二级指针操作(修改一级指针的值)
实例2:动态二维数组(二级指针)
实例3:三级指针操作(修改二级指针的值)
3. 多级指针的常见陷阱
4. 总结
1. 多级指针的核心原理
多级指针(如二级指针、三级指针)本质是 指向指针的指针,用于间接访问或修改其他指针的值。通过多级指针可以构建复杂的内存结构(如动态多维数组、链表中的指针传递等)。
1. 多级指针的定义
- 二级指针:存储一级指针的地址。
int a = 10;
int *p = &a; // 一级指针,指向int变量
int **pp = &p; // 二级指针,指向int*指针
- 三级指针:存储二级指针的地址。
int ***ppp = &pp; // 三级指针,指向int**指针
2. 内存结构示意图
栈内存布局:
+------+ +------+ +------+
| ppp | ----> | pp | ----> | p | ----> a (值=10)
+------+ +------+ +------+
地址:0x1000 地址:0x2000 地址:0x3000 地址:0x4000
- 定义另一个指针变量pps,并且把指针数组的首地址赋予指针pps。char *ps[5]={……}; char ** pps = ps; 如图所示

3. 多级指针的用途
-
动态创建多维数组:通过二级指针管理动态二维数组。
-
函数内修改外部指针:通过传递指针的指针,修改原始指针的值。
-
复杂数据结构:如链表、树结构中管理节点指针的指针。
2. 编程实例
实例1:二级指针操作(修改一级指针的值)
#include <stdio.h>// 函数:修改外部指针的指向
void changePointer(int **pp) {int b = 20;*pp = &b; // 通过二级指针修改一级指针的指向// 注意:此处b是栈变量,函数返回后其内存可能被覆盖!
}int main() {int a = 10;int *p = &a;printf("Before: *p = %d\n", *p); // 输出10changePointer(&p); // 传递指针的地址printf("After: *p = %d\n", *p); // 输出20(实际存在风险,b已失效)return 0;
}
输出(实际可能因编译器优化不同):
Before: *p = 10
After: *p = 20
警告:此示例中,changePointer函数内修改p指向栈变量b,函数返回后b的内存可能被回收,导致p成为野指针。正确做法应动态分配内存。
实例2:动态二维数组(二级指针)
#include <stdio.h>
#include <stdlib.h>int main() {int rows = 3, cols = 4;int **matrix; // 二级指针// 动态分配行指针数组matrix = (int**)malloc(rows * sizeof(int*));for (int i = 0; i < rows; i++) {matrix[i] = (int*)malloc(cols * sizeof(int)); // 分配每行内存for (int j = 0; j < cols; j++) {matrix[i][j] = i * cols + j; // 初始化数据}}// 打印二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {printf("%2d ", matrix[i][j]);}printf("\n");}// 释放内存for (int i = 0; i < rows; i++) free(matrix[i]);free(matrix);return 0;
}
输出:
0 1 2 3 4 5 6 7 8 9 10 11
内存示意图:
二级指针matrix(堆内存) 各行数据(堆内存)
+--------+ +-----+-----+-----+-----+
| 0x1000 | ------> 行0 -->| 0 | 1 | 2 | 3 |
+--------+ +-----+-----+-----+-----+
| 0x1008 | ------> 行1 -->| 4 | 5 | 6 | 7 |
+--------+ +-----+-----+-----+-----+
| 0x1010 | ------> 行2 -->| 8 | 9 | 10 | 11 |
+--------+ +-----+-----+-----+-----+
实例3:三级指针操作(修改二级指针的值)
#include <stdio.h>
#include <stdlib.h>void createMatrix(int ***ppp, int rows, int cols) {*ppp = (int**)malloc(rows * sizeof(int*)); // 分配行指针数组for (int i = 0; i < rows; i++) {(*ppp)[i] = (int*)malloc(cols * sizeof(int)); // 分配每行内存for (int j = 0; j < cols; j++) {(*ppp)[i][j] = i + j; // 初始化数据}}
}int main() {int **matrix = NULL; // 二级指针初始化为空int rows = 2, cols = 3;// 通过三级指针传递,动态创建二维数组createMatrix(&matrix, rows, cols);// 打印数据for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {printf("%2d ", matrix[i][j]);}printf("\n");}// 释放内存for (int i = 0; i < rows; i++) free(matrix[i]);free(matrix);return 0;
}
输出:
0 1 2 1 2 3
3. 多级指针的常见陷阱
1. 野指针风险
int **pp;
*pp = (int*)malloc(sizeof(int)); // 错误!pp未初始化,指向随机地址。
防御:确保多级指针指向合法内存后再操作。
2. 内存泄漏
int **matrix = malloc(3 * sizeof(int*));
// 忘记释放matrix和每行的内存!
防御:逐层释放内存,顺序为先释放子内存,再释放父指针。
3. 越级解引用
int a = 10;
int **pp = &a; // 错误!pp应为int**类型,但&a是int*类型。
防御:严格匹配指针层级和数据类型。
4. 总结

核心规则:
-
层级匹配:
n级指针需指向(n-1)级指针的地址。 -
内存管理:动态分配的多级指针必须逐层释放。
-
类型安全:解引用时需确保层级和数据类型一致,避免未定义行为。
相关文章:
C语言指针专题四 -- 多级指针
目录 1. 多级指针的核心原理 1. 多级指针的定义 2. 内存结构示意图 3. 多级指针的用途 2. 编程实例 实例1:二级指针操作(修改一级指针的值) 实例2:动态二维数组(二级指针) 实例3:三级指…...
本地部署 DeepSeek-R1 大模型
本地部署 DeepSeek-R1 大模型指南 1. 引言 1.1 DeepSeek-R1 模型简介 在人工智能的世界里,大型语言模型(LLM)正如一座巨大的宝库,里面储存着丰富的信息和无限的潜力。而DeepSeek-R1,就像那扇打开智慧之门的钥匙。它…...
深度学习的应用
目录 一、机器视觉 1.1 应用场景 1.2 常见的计算机视觉任务 1.2.1 图像分类 1.2.2 目标检测 1.2.3 图像分割 二、自然语言处理 三、推荐系统 3.1 常用的推荐系统算法实现方案 四、图像分类实验补充 4.1 CIFAR-100 数据集实验 实验代码 4.2 CIFAR-10 实验代码 深…...
想学习Python编程,应该如何去学习呢
学习Python编程是一个循序渐进的过程,以下是一个详细的学习路径和建议: 一、基础入门 安装Python环境: 从Python官方网站下载并安装适合你操作系统的Python版本。确保将Python添加到系统路径中,以便在命令行中方便地访问。 学习…...
RabbitMQ 多种安装模式
文章目录 前言一、Windows 安装 RabbitMq1、版本关系2、Erlang2.1、下载安装 Erlang 23.12.2、配置 Erlang 环境变量 3、RabbitMQ3.1、下载安装 RabbitMQ 3.8.93.2、环境变量3.3、启动RabbitMQ 管理插件3.3、RabbitMQ3.4、注意事项 二、安装docker1、更新系统包:2、…...
吴恩达深度学习——有效运作神经网络
内容来自https://www.bilibili.com/video/BV1FT4y1E74V,仅为本人学习所用。 文章目录 训练集、验证集、测试集偏差、方差正则化正则化参数为什么正则化可以减少过拟合Dropout正则化Inverted Dropout其他的正则化方法数据增广Early stopping 归一化梯度消失与梯度爆…...
《DeepSeek-R1 问世,智能搜索领域迎来新变革》
DeepSeek-R1是由DeepSeek公司开发的一款创新型人工智能模型,自2024年5月7日发布以来,迅速在AI领域引起广泛关注。该模型凭借其卓越的语言理解能力、高效的数据处理能力、自适应学习能力、高安全性与可靠性以及广泛的应用场景与拓展性,在众多人…...
深入解析 Linux 内核中的页面错误处理机制
在现代操作系统中,页面错误(Page Fault)是内存管理的重要组成部分。当程序试图访问未映射到物理内存的虚拟内存地址时,CPU 会触发页面错误异常。Linux 内核通过一系列复杂的机制来处理这些异常,确保系统的稳定性和性能。本文将深入解析 Linux 内核中处理页面错误的核心代码…...
Java手写简单Merkle树
Java手写Merkle树代码 package com.blockchain.qgy.component;import com.blockchain.qgy.model.MerkleTreeNode; import com.blockchain.qgy.util.SHAUtil;import java.util.*;public class MerkleTree<T> {//merkle树private List<MerkleTreeNode<T>> lis…...
DDD - 微服务架构模型_领域驱动设计(DDD)分层架构 vs 整洁架构(洋葱架构) vs 六边形架构(端口-适配器架构)
文章目录 引言1. 概述2. 领域驱动设计(DDD)分层架构模型2.1 DDD的核心概念2.2 DDD架构分层解析 3. 整洁架构:洋葱架构与依赖倒置3.1 整洁架构的核心思想3.2 整洁架构的层次结构 4. 六边形架构:解耦核心业务与外部系统4.1 六边形架…...
数据结构与算法之二叉树: LeetCode LCP 10. 二叉树任务调度 (Ts版)
二叉树任务调度 https://leetcode.cn/problems/er-cha-shu-ren-wu-diao-du/description/ 描述 任务调度优化是计算机性能优化的关键任务之一。在任务众多时,不同的调度策略可能会得到不同的总体执行时间,因此寻求一个最优的调度方案是非常有必要的 通…...
在AWS上使用KMS客户端密钥加密S3文件,同时支持PySpark读写和Snowflake导入
现有AWS EMR集群上运行PySpark代码,可以读写S3上的数据文件,Snowflake数据仓库也需要导入S3上的文件到表。现在要用AWS KMS有客户端密钥加密S3上的文件,同时允许PySpark代码,可以读写S3上的数据文件,Snowflake数据仓库…...
玩转大语言模型——配置图数据库Neo4j(含apoc插件)并导入GraphRAG生成的知识图谱
系列文章目录 玩转大语言模型——使用langchain和Ollama本地部署大语言模型 玩转大语言模型——ollama导入huggingface下载的模型 玩转大语言模型——langchain调用ollama视觉多模态语言模型 玩转大语言模型——使用GraphRAGOllama构建知识图谱 玩转大语言模型——完美解决Gra…...
如何进行API版本控制?
一、URI路径版本控制(Path Versioning) 通过在API的URL路径中包含版本号来实现。例如: /api/v1/products /api/v2/products 这种方法最为直观,用户可以根据URL判断版本。它的优点是简单易懂,容易实现。但如果接口变动频繁,可能会导致大量的路径不同版本的接口需要维护…...
计算机毕业设计Python+CNN卷积神经网络考研院校推荐系统 考研分数线预测 考研推荐系统 考研爬虫 考研大数据 Hadoop 大数据毕设 机器学习
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
### 2024 江西省赛题解(A,C,D,G,H,J,K,L) BEFI待补
A. 输出 a b c abc abc 即可。 void slove () {int a, b, c;cin >> a >> b >> c;cout << (a b c) << endl; }B. C. 如果 ∑ i 1 n a i S \sum_{i1}^{n}a_iS ∑i1naiS 那么存在所有人说的都是真话的可能。 否则,我们…...
Ruby 类和对象
Ruby 类和对象 引言 在软件开发中,类和对象是面向对象编程(OOP)的核心概念。Ruby 作为一种动态、解释型编程语言,也以简洁的方式支持面向对象编程。本文将深入探讨 Ruby 中的类和对象,包括它们的定义、创建、使用以及一些高级特性。 类与对象的定义 类 在 Ruby 中,类…...
【自学笔记】JavaWeb的重点知识点-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 JavaWeb知识点一、基础概念二、项目结构三、Tomcat服务器四、数据库连接(JDBC)五、前端技术六、高级技术 总结 以下是JavaWeb知识点的MD格式…...
OpenCV:闭运算
目录 1. 简述 2. 用膨胀和腐蚀实现闭运算 2.1 代码示例 2.2 运行结果 3. 闭运算接口 3.1 参数详解 3.2 代码示例 3.3 运行结果 4. 闭运算的应用场景 5. 注意事项 相关阅读 OpenCV:图像的腐蚀与膨胀-CSDN博客 OpenCV:开运算-CSDN博客 1. 简述…...
智云-一个抓取web流量的轻量级蜜罐-k8s快速搭建教程
智云-一个抓取web流量的轻量级蜜罐-k8s快速搭建教程 github地址 https://github.com/xiaoxiaoranxxx/POT-ZHIYUN k8s搭建教程 首先下载代码文件 git clone https://github.com/xiaoxiaoranxxx/POT-ZHIYUN.git cd POT-ZHIYUN编译镜像 代码相关文件在github https://github.com/x…...
万物皆有联系:驼鸟和布什
布什?一块布十块钱吗?不是,大家都知道,美国有两个总统,叫老布什和小布什,因为两个布什总统(父子俩),大家就这么叫来着,目的是为了好区分。 布什总统的布什&a…...
nodejs:js-mdict 的下载、安装、测试、build
js-mdict 项目的目录结构:js-mdict 项目教程 js-mdict 下载地址: js-mdict-master.zip 先解压到 D:\Source\ js-mdict 6.0.2 用了 ts (TypeScript) 和 Jest,增加了应用开发的难度,因为先要了解 ts 和 Jest。 参阅:测试与开发&a…...
< OS 有关 > 阿里云:轻量应用服务器 的使用 :轻量化 阿里云 vpm 主机
原因: < OS 有关 > 阿里云:轻量应用服务器 的使用 :从新开始 配置 SSH 主机名 DNS Tailscale 更新OS安装包 最主要是 清除阿里云客户端这个性能杀手-CSDN博客 防止 I/O 祸害系统 操作: 查看进程&#x…...
sqlzoo答案4:SELECT within SELECT Tutorial
sql练习:SELECT within SELECT Tutorial - SQLZoo world表: namecontinentareapopulationgdpAfghanistanAsia6522302550010020343000000AlbaniaEurope28748283174112960000000AlgeriaAfrica238174137100000188681000000AndorraEurope46878115371200000…...
Ubuntu全面卸载mysql
如果你已经看到whereis mysql输出了与MySQL相关的路径,说明MySQL仍然存在于系统中。要卸载MySQL,可以按照以下步骤操作,确保完全删除所有相关的文件和配置: 1. 停止MySQL服务 首先,停止MySQL服务: sudo …...
SOME/IP--协议英文原文讲解3
前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 Note: Thi…...
350.两个数组的交集 ②
目录 题目过程解法 题目 给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑…...
药店药品销售管理系统的设计与实现
标题:药店药品销售管理系统的设计与实现 内容:1.摘要 摘要:本文介绍了药店药品销售管理系统的设计与实现。该系统旨在提高药店的运营效率和管理水平,通过信息化手段实现药品销售、库存管理、财务管理等功能。本文详细阐述了系统的需求分析、设计思路、技…...
汽车蓝牙钥匙定位仿真小程序
此需求来自于粉丝的真实需求,假期没事,牛刀小试。 一、项目背景 如今,智能车钥匙和移动端定位技术已经相当普及。为了探索蓝牙 Beacon 在短距离定位场景下的可行性,我们搭建了一个简易原型:利用 UniApp 在移动端采集蓝牙信标的 RSSI(信号强度),通过三边定位算法估算钥…...
unity学习24:场景scene相关生成,加载,卸载,加载进度,异步加载场景等
目录 1 场景数量 SceneManager.sceneCount 2 直接代码生成新场景 SceneManager.CreateScene 3 场景的加载 3.1 用代码加载场景,仍然build setting里先加入配置 3.2 卸载场景 SceneManager.UnloadSceneAsync(); 3.3 同步加载场景 SceneManager.LoadScene 3.3.…...
