当前位置: 首页 > news >正文

动态数组

** p 相当于一个指向指针的指针

比如我去创建一个 int 数组,用

#include <stdio.h>int main() {int *p=(int *)malloc(4*sizeof(int));for(int i=0;i<4;i++) p[i]=i+1;for(int i=0;i<4;i++) printf("%d ",p[i]);return 0;
}

那我开一个都是指针的数组,比如说一个行指针数组,里面存放着二维数组的行指针。那么,此时,指向指针的指针,相当于把数组元素换成 int * 了,那么你自然的指向这个数组就要多带一个 *。

#include <stdio.h>int main() {int **p=(int **)malloc(4*sizeof(int*));int tot=1;for(int i=0;i<4;i++) {p[i]=(int *)malloc(4*sizeof(int)); //p[i] 为一个指针,指向的应该是这一行第一个元素的地址 for(int j=0;j<4;j++) p[i][j]=++tot;}for(int i=0;i<4;i++) {for(int j=0;j<4;j++) printf("%d ",p[i][j]);printf("\n");}return 0;
}

动态二维数组作为参数详解

一、为什么需要动态二维数组?

在讲解具体用法前,我们先理解为什么需要动态二维数组。静态数组在编译时就必须确定大小,但很多实际场景中,数组大小需要在运行时才能确定:

// 静态数组 - 大小固定
int static_matrix[10][20]; // 只能处理10×20的矩阵// 但实际需求可能是:
int rows, cols;
printf("请输入矩阵的行数和列数: ");
scanf("%d %d", &rows, &cols); // 用户输入决定大小

这时候就需要动态二维数组来解决这个问题。

二、动态二维数组的内存模型

理解动态二维数组的关键是要明白它的内存布局与静态二维数组不同:

静态二维数组(连续存储)
┌───┬───┬───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ ← 所有元素连续存储
└───┴───┴───┴───┴───┴───┘
matrix[0]    matrix[1]动态二维数组(非连续存储)
┌───────┐    ┌───┬───┬───┐
│ 地址1 │───→│ 1 │ 2 │ 3 │ ← 第0行
└───────┘    └───┴───┴───┘
┌───────┐    ┌───┬───┬───┐
│ 地址2 │───→│ 4 │ 5 │ 6 │ ← 第1行
└───────┘    └───┴───┴───┘
┌───────┐    ┌───┬───┬───┐
│ 地址3 │───→│ 7 │ 8 │ 9 │ ← 第2行
└───────┘    └───┴───┴───┘

关键区别:动态二维数组的每一行都是独立分配的内存块,可能不连续!

三、创建动态二维数组的完整流程

3.1 分步创建过程

#include <stdio.h>
#include <stdlib.h>int main() {int rows, cols;// 步骤1:获取矩阵大小printf("请输入矩阵的行数和列数: ");scanf("%d %d", &rows, &cols);// 步骤2:创建"行指针数组"int **matrix = (int**)malloc(rows * sizeof(int*));if (matrix == NULL) {printf("内存分配失败!\n");return -1;}// 步骤3:为每一行分配内存for (int i = 0; i < rows; i++) {matrix[i] = (int*)malloc(cols * sizeof(int));if (matrix[i] == NULL) {printf("第%d行内存分配失败!\n", i);// 需要释放之前已分配的内存for (int j = 0; j < i; j++) {free(matrix[j]);}free(matrix);return -1;}}// 步骤4:使用矩阵printf("动态二维数组创建成功!大小: %d×%d\n", rows, cols);// 步骤5:释放内存(重要!)for (int i = 0; i < rows; i++) {free(matrix[i]);  // 先释放每一行}free(matrix);         // 再释放行指针数组return 0;
}

四、动态二维数组作为函数参数

4.1 函数声明和定义

由于动态二维数组实际上是"指针的指针",所以函数参数应该使用 int ** 类型:

#include <stdio.h>
#include <stdlib.h>// 函数声明:动态二维数组作为参数
void initialize_matrix(int **matrix, int rows, int cols);
void print_matrix(int **matrix, int rows, int cols);
void free_matrix(int **matrix, int rows);// 创建动态二维数组的函数
int** create_matrix(int rows, int cols) {int **matrix = (int**)malloc(rows * sizeof(int*));if (matrix == NULL) return NULL;for (int i = 0; i < rows; i++) {matrix[i] = (int*)malloc(cols * sizeof(int));if (matrix[i] == NULL) {// 分配失败,清理已分配的内存for (int j = 0; j < i; j++) {free(matrix[j]);}free(matrix);return NULL;}}return matrix;
}// 初始化矩阵
void initialize_matrix(int **matrix, int rows, int cols) {for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {matrix[i][j] = i * cols + j + 1; // 填充数据}}
}// 打印矩阵
void print_matrix(int **matrix, int rows, int cols) {printf("矩阵内容:\n");for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {printf("%4d", matrix[i][j]);}printf("\n");}
}// 释放矩阵内存
void free_matrix(int **matrix, int rows) {for (int i = 0; i < rows; i++) {free(matrix[i]);}free(matrix);
}int main() {int rows = 3, cols = 4;// 创建动态二维数组int **my_matrix = create_matrix(rows, cols);if (my_matrix == NULL) {printf("创建矩阵失败!\n");return -1;}// 使用函数操作矩阵initialize_matrix(my_matrix, rows, cols);print_matrix(my_matrix, rows, cols);// 释放内存free_matrix(my_matrix, rows);return 0;
}

五、理解 int **matrix 的含义

这是最让人困惑的部分,我们来拆解理解:

int **matrix;  // 这是什么?// 分解理解:
// 1. matrix 是一个指针,指向什么?
// 2. 它指向的是 int* 类型(整数指针)
// 3. 所以 matrix 是"指向整数指针的指针"// 实际内存布局:
matrix → [指针0] → [整数00, 整数01, 整数02...]  // 第0行[指针1] → [整数10, 整数11, 整数12...]  // 第1行  [指针2] → [整数20, 整数21, 整数22...]  // 第2行

访问元素的各种等价写法:

matrix[i][j]        // 最直观的写法
*(matrix[i] + j)    // 先取第i行指针,再偏移j个元素
*(*(matrix + i) + j) // 完全用指针运算

六、完整实战示例:矩阵运算

#include <stdio.h>
#include <stdlib.h>// 矩阵相加:C = A + B
int matrix_add(int **A, int **B, int **C, int rows, int cols) {for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {C[i][j] = A[i][j] + B[i][j];}}return 0;
}// 矩阵转置
int matrix_transpose(int **src, int **dst, int rows, int cols) {for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {dst[j][i] = src[i][j];  // 行列互换}}return 0;
}int main() {int rows = 2, cols = 3;// 创建三个矩阵int **A = create_matrix(rows, cols);int **B = create_matrix(rows, cols); int **C = create_matrix(rows, cols);int **T = create_matrix(cols, rows);  // 转置矩阵大小互换// 初始化A, Binitialize_matrix(A, rows, cols);initialize_matrix(B, rows, cols);// 矩阵相加matrix_add(A, B, C, rows, cols);printf("矩阵A:\n");print_matrix(A, rows, cols);printf("矩阵B:\n"); print_matrix(B, rows, cols);printf("矩阵C = A + B:\n");print_matrix(C, rows, cols);// 矩阵转置matrix_transpose(A, T, rows, cols);printf("A的转置矩阵:\n");print_matrix(T, cols, rows);// 释放所有内存free_matrix(A, rows);free_matrix(B, rows);free_matrix(C, rows); free_matrix(T, cols);return 0;
}

七、常见错误与调试技巧

7.1 内存泄漏检测

// 错误示例:只释放了部分内存
void wrong_free(int **matrix, int rows) {free(matrix); // 只释放了行指针数组,没释放每一行!// 应该先释放所有 matrix[i],再释放 matrix
}// 正确做法:按分配顺序逆序释放
void correct_free(int **matrix, int rows) {for (int i = 0; i < rows; i++) {free(matrix[i]);  // 释放每一行}free(matrix);         // 释放行指针数组
}

7.2 边界检查

void safe_access(int **matrix, int rows, int cols, int i, int j) {if (i < 0 || i >= rows || j < 0 || j >= cols) {printf("索引越界: (%d, %d)\n", i, j);return;}printf("matrix[%d][%d] = %d\n", i, j, matrix[i][j]);
}

八、总结

动态二维数组作为参数的核心要点:

  1. 理解 int ** 类型:这是"指针的指针",指向一个指针数组
  2. 内存非连续:每一行独立分配,可能不连续存储
  3. 必须传递行列参数:函数内无法自动获取大小信息
  4. 严格的内存管理:分配时检查返回值,释放时按正确顺序
  5. 灵活的尺寸:可以创建不规则二维数组(每行长度不同)

通过这种理解,你就能熟练使用动态二维数组来解决各种复杂的编程问题了!

http://www.jsqmd.com/news/58652/

相关文章:

  • Python基于PyTorch实现多输入多输出进行LSTM循环神经网络回归预测项目实战 - 实践
  • 轻松刷入OpenWrt:红米AC3000与小米CR8806/8808/8809实战教程
  • Solon AI 开发学习8 - chat - Vision(理解)图片、声音、视频
  • 安卓开发 Log 日志不显示在androidstudio里
  • Python全栈项目:基于Django的电子商务平台编写
  • 06.Servlet容器
  • PbootCMS留言发送到邮箱,邮件标题如何修改
  • 23、【Ubuntu】【远程编写】内网穿透:SSH 反向隧道
  • 【STM32】定时器、PWM - 教程
  • 大模型安全:共享 GPU 本地内存泄露
  • React Hooks闭包陷阱导致的状态错乱,怎么办
  • MAF快速入门(4)多Agent工作流编排
  • 人工智能之数据分析 Pandas:第一章 简介和安装
  • Dbeaver - 一些好用的设置
  • 内存管理-54-slub-1-文档翻译等 - Hello
  • MYSQL - 数据库优化:慢查询
  • 完整教程:AI代码开发宝库系列:PDF文档解析MinerU
  • 2025年烤兰打包带厂家口碑排行,这十家备受推崇,打包带钢/光伏支架打包带/电镀锌打包带/铜棒打包带/镀锌打包扣烤兰打包带销售厂家推荐排行榜
  • 实用指南:海外短剧系统开发:应对高并发访问的数据库优化与缓存策略
  • 2025年12月AI SEO优化公司推荐:解锁智能搜索流量新密码
  • 易路:连锁餐饮人力资源数智化转型升级新引擎
  • 尘埃粒子计数器生产厂家联系电话,大流量尘埃粒子计数器/粒子计数器/尘埃粒子计数器/悬浮粒子计数器/尘埃粒子计数器厂家排名
  • 尘埃粒子计数器供应商推荐榜,台式粒子计数器/尘埃粒子计数器在线监测系统/大流量尘埃粒子计数器/尘埃粒子计数器公司电话
  • 2025年AI教育培训供应商推荐榜:聚焦企业AI培训,精选优质机构供参考
  • python笔记-循环
  • 2025年12月ChatGPT优化排名公司推荐
  • 2025年12月西安旧房翻新公司TOP5推荐:装修/家装/室内设计领衔企业
  • 2025年12月深圳艺考生文化课培训推荐:聚焦分层教学与艺考政策适配力!
  • 2025 美本留学机构十大推荐:全维服务护航,头部机构引领申请路
  • 2025年AI教育培训课程推荐榜:覆盖AI培训全场景指南