C语言指针专题四 -- 多级指针

news/2025/2/1 8:04:36 标签: c语言, 开发语言, 数据结构, 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); // 输出10

    changePointer(&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)级指针的地址。

  • 内存管理:动态分配的多级指针必须逐层释放。

  • 类型安全:解引用时需确保层级和数据类型一致,避免未定义行为。


http://www.niftyadmin.cn/n/5839176.html

相关文章

UE5制作视差图

双目深度估计开源数据集很多都是用UE制作的&#xff0c;那么我们自己能否通过UE制作自己想要的场景的数据集呢。最近花了点时间研究了一下&#xff0c;分享给需要的小伙伴。 主要使用的是UnrealCV插件&#xff0c;UnrealCV是一个开源项目&#xff0c;旨在帮助计算机视觉研究人…

从0开始,来看看怎么去linux排查Java程序故障

一&#xff0c;前提准备 最基本前提&#xff1a;你需要有liunx环境&#xff0c;如果没有请参考其它文献在自己得到local建立一个虚拟机去进行测试。 有了虚拟机之后&#xff0c;你还需要安装jdk和配置环境变量 1. 安装JDK&#xff08;以OpenJDK 17为例&#xff09; 下载JDK…

[EAI-029] RoboVLMs,基于VLM构建VLA模型的消融研究

Paper Card 论文标题&#xff1a;Towards Generalist Robot Policies: What Matters in Building Vision-Language-Action Models 论文作者&#xff1a;Xinghang Li, Peiyan Li, Minghuan Liu, Dong Wang, Jirong Liu, Bingyi Kang, Xiao Ma, Tao Kong, Hanbo Zhang, Huaping L…

优雅管理Python2 and python3

python2 和 python3&#xff0c; 由于没有像其他软件的向下兼容&#xff0c;必须同时安装Python2 和Python3 &#xff0c;介绍在linux和windows下优雅管理。 一、linux中安装Python2和Python3 linux 中用conda 创建虚拟环境&#xff0c;来管理不同版版工具 由于主流使用Python3…

计算机网络之计算机网络的分类

计算机网络可以根据不同的角度进行分类&#xff0c;以下是几种常见的分类方式&#xff1a; 1. 按照规模和范围&#xff1a; 局域网&#xff08;LAN&#xff0c;Local Area Network&#xff09;&#xff1a;覆盖较小范围&#xff08;例如一个建筑物或校园&#xff09;&#xf…

【产品经理学习案例——AI翻译棒出海业务】

前言&#xff1a; 本文主要讲述了硬件产品在出海过程中&#xff0c;翻译质量、翻译速度和本地化落地策略是硬件产品规划需要考虑的核心因素。针对不同国家&#xff0c;需要优化翻译质量和算法&#xff0c;关注市场需求和文化差异&#xff0c;以便更好地满足当地用户的需求。同…

Python3 + Qt5:实现AJAX异步更新UI

使用 Python 和 Qt5 开发时异步加载数据的方法 在开发使用 Python 和 Qt5 的应用程序时&#xff0c;为了避免在加载数据时界面卡顿&#xff0c;可以采用异步加载的方式。以下是几种实现异步加载的方法&#xff1a; 1. 使用多线程&#xff08;QThread&#xff09; 通过将数据…

PyDeequ库在AWS EMR启动集群中数据质量检查功能的配置方法和实现代码

PyDeequ是一个基于Apache Spark的Python API&#xff0c;专门用于定义和执行“数据单元测试”&#xff0c;从而在大规模数据集中测量数据质量。 PyDeequ框架在PySpark代码中提供了全面的数据质量检查功能&#xff0c;能够帮助用户&有效地监控和提升大规模数据集的数据质量。…