目录
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)
级指针的地址。 -
内存管理:动态分配的多级指针必须逐层释放。
-
类型安全:解引用时需确保层级和数据类型一致,避免未定义行为。