当前位置: 首页 > 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.rkmt.cn/news/69055.html

相关文章:

  • 【Linux进阶系列】:线程(上) - 详解
  • Solon AI 开发学习8 - chat - Vision(理解)图片、声音、视频
  • Python全栈项目:基于Django的电子商务平台编写
  • 【触想智能】工业触控一体机在工业应用中扮演的角色以及其应用场景分析
  • 租房买房必看4门口乱堆杂物,正在悄悄“截断”全家人的好运气!
  • 大模型安全:共享 GPU 本地内存泄露
  • 2025年12月AI SEO优化公司推荐:解锁智能搜索流量新密码
  • 2025年12月ChatGPT优化排名公司推荐
  • 2025年AI教育培训课程推荐榜:覆盖AI培训全场景指南
  • 2025年12月西安装修家装公司TOP5推荐:老房翻新/室内设计优选企业
  • 模切机厂家有哪些?国内知名企业推荐
  • Webpack/Vite等构建工具打包后,线上代码报错但本地正常,怎么办?
  • 哪些品牌的妇科炎症外用药效果好
  • 2025年热镀锌带钢口碑厂家TOP10,实力见证,镀锌打包扣/镀锌打包钢带/烤漆打包带/冷镀锌打包带/打包铁条热镀锌带钢生产厂家
  • 漆面保护膜品牌公司排名:国内优质车膜品牌推荐
  • 推荐专业的北京离婚财产纠纷律师及服务解析
  • 推荐靠谱的车衣品牌:市场热门选择及特点解析
  • 争取孩子抚养权找哪个律师靠谱?专业选择参考
  • 北京口碑好的涉外离婚律师选择指南与实务解析
  • 哪些AI企业有投资价值?聚焦行业潜力标的
  • 第十周第三天10.3
  • 北京知名婚姻律所推荐:聚焦婚姻家事法律服务机构
  • 2025 年热熔胶复合机最新推荐榜,技术实力与市场口碑深度解析,筛选优质源头厂家全自动/自动/无纺布/碳布/pur 热熔胶复合机公司推荐
  • 国内游旅行社哪家有优惠活动?2025年热门选择参考
  • OOP实验四
  • 2025 十大艺术涂料厂家推荐:品质与美学的巅峰对决
  • 2025年最新垃圾分类设备厂家TOP5优选指南
  • 专业的工作手机推荐:红鹰工作手机专业靠谱之选
  • CentOS9上Let’s Encrypt自动续签
  • 微波烘干设备哪家好?国内优质企业及业务特点解析