1、关于定义二维数组

先说在前面,一般的我们说的C/C++中的二维数组是定义在栈中的二维数组。比如定义了一个array[3][4],那就指的是定义了一个三行四列的矩阵形状的二维数组,如下图所示。这样的矩阵在内存中是以箭头右边的方式存放的,也就是说实际上我们定义的二维数组在内存中仍然像是一维数组那样连续存储的。可以想象为把一个矩阵一层层伸展铺平。

因此可以使用如下方法定义二维数组:

方法一: 直接确定二维数组的行和列数

/* 可以使用下面的方法来初始化二维数组* 也就是直接将二维数组铺平,写成一维数组的形式*/
int array[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};/* 可以使用标准的二维数组的初始化方式*/
int array[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};

方法二: 不用指明二维数组的行数,但要指明列数

下面的一种写法本质上是定义了一个数组指针

/* 经典的写法*/
int array[][4];/* 一种更帅的写法,本质上是定义了一个数组指针*/
int (*array)[4];

方法三: 动态分配的方式,这种写法比较灵活,在定义的时候不需要指明二维矩阵的行数和列数

/* 使用动态分配内存的形式,用malloc*/
int **array // array[M][N]
array = (int **)malloc(M * sizeof(int *));
for(int i = 0; i < M; i++) {array[i] = (int *)malloc(N * sizeof(int));
}// 释放
for(int i = 0; i < M; i++)free(array[i]);
free(array);/* 使用动态分配内存的形式,用new*/
int **array // array[M][N]
array = new int*[M];
for(int i = 0; i < M; i++) {array[i] = new int[N];
}// 释放
for(int i = 0; i < M; i++) delete [] array[i];
delete [] array;

不过按照这种形式实现的二维数组本质上已经不是我们之前说的传统的二维数组 了,采用此种方法定义的二维数组的结构如下图所示,这样的二维数组在堆上分配内存。也就是说这样实现的二维数组本质上已经是指针数组了。使用这样的方式分配二维数组空间之后,可以使用array[i][j]进行数组的读写操作没有问题,但是应该知道不同行的内存空间不一定连续。这是因为每一行的数组的内存都是使用malloc分配的,多次使用malloc分配的内存空间并不一定是连续的,这与在栈上分配的二维矩阵有着根本的不同,比如同样的对于顶底的二维数组array[3][4],不能再使用array[0][4]来访问array[1][0]了,这样会导致地址越界,就是因为地址不一定连续了。

2 、二维数组的传参写法

使用二维数组作为参数,可以有以下几种写法。

1 使用动态分配内存的方式申请空间,可以使用**传递参数

希望在使用二维数组的时候保持良好的编程习惯,使用哪种方法定义的就使用哪种方式传参,这样对于保持良好的编码习惯有好处,对于别人阅读你的代码也有好处。

#include <iostream>
using namespace std;int func1(int **arr) {cout << arr[0][0];arr[0][2] = 20;return 0;
}int main()
{int **arrayint row = 3;int col = 4;array = (int **)malloc(row * sizeof(int *));for (int i = 0; i < row; i++) {array[i] = (int *)malloc(col * sizeof(int));}memset(*array, 0, sizeof(int)*row*col);array[0][1] = 100;func1(array);cout << array[0][2];return 0;
}

2 使用二维数组的传统定义方法传递参数

如果把数组名作为函数的参数的话,在编译的时候这个数组参数会自动退化为指针,因此以下两种写法虽然不同,但在编译之后是一样的,数组会退化成数组指针。

#include <iostream>
using namespace std;/** 以下两种写法本质上是一样的*/
int func1(int (*arr)[4]) {cout << arr[0][0] << endl;arr[0][2] = 20;return 0;
}int func2(int arr[][4]) {cout << arr[0][0] << endl;arr[0][2] = 20;return 0;
}int main()
{int array[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};array[0][1] = 100;func1(array);cout << array[0][2] << endl;return 0;
}

正是因为这个问题,在定义如下类似求数组大小的函数的时候必须将数组引用传递!否则数组会退化为一个指针,无法正确的使用sizeof运算符求出数组a所占内存空间大小。

template<class T>
int GetArrayLen(T& a)
{return sizeof(a)/sizeof(a[0]);
}

C/C++二维数组总结相关推荐

  1. Java IDEA Debug进制二维数组

    1.Debug模式 1.1 什么是Debug模式 是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序. 1.2 Debug介绍与操作流程 如何加断点 选择 ...

  2. Python数据挖掘1:创建一位数组和二维数组,取最大最小值,切片

    ''' 来源:天善智能韦玮老师课堂笔记 1.numpy 可以高效处理数据.提供数组支持.很多模块都依赖他,比如pandas.scipy.matplotlib都依赖他,所以这个模块是基础. 2.pand ...

  3. Numpy 生成 Bool型数组、一维转多维数组reshape、多维转一维数组、替换数组元素、提取数组元素、数组交集、差集、过滤数组元素、二维数组反转行、交换数组维度

    1. 创建一个 [3,5] 所有元素为 True 的数组 In [162]: b = np.ones((3,5), dtype=bool)In [163]: b Out[163]: array([[ ...

  4. Numpy 一维、二维数组、size/dtype/shape属性、数组函数arange/linspace/logspace /diag/zeros/ones/random 、多维数组索引和筛选)

    参考: https://gitbook.cn/gitchat/column/undefined/topic/5e3bceadec8d9033cf924665 打开 IPython ,创建 Python ...

  5. C++二维数组名与数组指针的思考

    二维数组名和数组指针可以当做一个东西用,但两者之间的含义是不同的. 二维数组名是一个指向数组中所有元素的指针,而数组指针是一个行指针.体现在sizeof()上的不同. #include <ios ...

  6. 建立二维数组_二维数组的 DP

    寻找不同路径和 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为"Start" ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标 ...

  7. c语言N*N的二维数组,c语言高手帮个忙(请先看问题,好解答

    程序定义了N×N的二维数组,并在主函数中自动赋值.请编写函数fun(int a[ ][ N ],int n),该函数的功能是使数组左下半三角元素中的值加上n.例如:若n的值为3,a数组中的值为a=2 ...

  8. cout 数组_C语言学习笔记(十)二维数组内存预设

    1 问题描述 二维数组存储数据数量根据其他方法间接获得: 为当前数据数量申请内存: 2 相关程序 #include --2020.11.23--

  9. 剑指offer:面试题04. 二维数组中的查找

    题目:二维数组中的查找 在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该 ...

  10. 求二维数组最大子数组

    结对队友:胡康臻.杨寒寒 1.设计思想: 首先定义产生二维数组,定义可输入二维数组行和列,各位数随机产生: 然后进行最大子数组的求和比较,从每行的第一个数为子数组的起点开始进行不同的子数组遍历比较,只 ...

最新文章

  1. centos7下nginx配置
  2. Linux chown命令:给资源绑定用户权限
  3. java下载zip_从Servlet Java下载zip
  4. 【动态规划】 石子合并问题(环形) (ssl 1597)
  5. eclipse 取消自动括号补全
  6. 19-mysql-约束
  7. windows server 2008R2 部署WSUS 服务
  8. UVA12279 LA4853 Emoogle Balance【水题】
  9. Kubernetes 两步验证 - 使用 Serverless 实现动态准入控制
  10. 步进电机 迷你L298N 2路直流电机驱动模块 正反转 PWM调速 双H桥
  11. BRVAH官方使用指南(持续更新)
  12. 关于CSS中 用“rem 在谷歌浏览器下的问题
  13. Starting Programe
  14. MyEclipse豆沙绿颜色设置
  15. 机智云(esp8266)与74hc595控制16路继电器
  16. java FFMPEG调取usb摄像头,截取视频,添加文字和时间水印
  17. 网络工程师必知:网关与防火墙有什么区别?
  18. Android Service的启动过程
  19. SQL中日期与时间类型及函数
  20. 关于联想小新Air14(或小新系列)更新系统后蓝屏的解决方法(关于windows系统更新安装补丁后出现蓝屏的解决方法)

热门文章

  1. 顺丰科技数据库中间件研发工程师面试经历
  2. 短信(SMS)的解释分类以及原理
  3. DC电源插头工作原理
  4. GPS定位精度指标含义
  5. Android项目猜纸牌游戏之一 界面设计和资源文件的设计
  6. 开发工作流程_您应该了解的9个开发工作流程升级
  7. esp8266舵机驱动_使用Arduino和ESP8266通过网页控制舵机
  8. H5及微信小程序实测可用——监听手机返回键操作
  9. 微信小程序单页开发之 min-cli
  10. 无法打开位置服务器,电脑的定位功能无法打开怎么办?