使用malloc在堆上创建二维数组

先回顾new在堆上分配内存,见我的博文点击打开链接 C/C++的数据类型判断的最后总结的:如果new后边的类型是非数组类型,那么返回的类型是这种类型的指针(最内层的指针,是其本质);如果new后边的类型是数组,那么返回的类型是数组退化为指针之后的类型。关于退化,见我的博文点击打开链接中关于C/C++赋值中的退化规则。

malloc的返回值是void* 类型的泛型指针,需要强制类型转换为其它指针类型来赋值。

分配连续的内存给二维数组:

    int rows = 10;
    int columns = 5;
    int  *p[10];    //p是指针数组  数组在三中情况之外都相当于指针常量
    int **matrix = p;
    
    matrix[0] = (int*)malloc(rows*columns*sizeof(int));
    for (int i = 1; i < rows; ++i)
    {
        matrix[i] = matrix[0] + i*columns;
    }
或者这样,跟要求连续空间的二维数组保持一致:

int rows = 10;
	int columns = 5;
	int **matrix = (int**)malloc(rows*sizeof(int*));
	matrix[0] = (int*)malloc(rows*columns*sizeof(int));
	for (int i = 1; i < rows; ++i)
	{
		matrix[i] = matrix[0] + i*columns;
		cout << matrix[i] << endl;
	}

需要注意的是,这里一定要有p这个数组,而不能简单的定义一个指针变量

int *p;

int **matrix = &p;  

原因是matrx[1] , matrix[2]...都发生了越界,他们都不是定义的变量的地址(指针),不能去改写。


分配非要求连续空间的二维数组:

int rows = 10;
int columns = 5;
int** matrix = (int**)malloc(rows*sizeof(int*));   //在堆上构建一个中间数组,中间数组的每个元素来管理一行
    for (int i = 0; i < rows; ++i)
    {
        matrix[i] = (int*)malloc(columns*sizeof(int));
    }
或者像上边一样,管理的一个一维数组在栈上:

        int rows = 10;
	int columns = 5;
	int *p[10];
	int ** matrix = p;
	for (int i = 0; i < rows; ++i)
	{
		p[i] = (int*)malloc(columns*sizeof(int));
	}

可以看到无论哪种方式,都需要借助一个中间层数组来管理。于是可以看到C++中new 操作符的强大优势,分配二维数组,直接new int [10][5],   简单不容易出错, hiahia.

二维数组若是退化,会退化为数组指针,C/C++中的数组本身是按行优先的线性存储,二维数组名是指向第0行的数组指针,终极的写法如下:

typedef int(*Arr)[5];
Arr p = (Arr)malloc(sizeof(int)* 10 * 5);  //p是数组指针,指向的一维的维数是5
                                                  //malloc分配的是连续的线性空间  一共有10个这样的一维数组

其实无论怎样,最终都需要malloc() 出 sizeof(int)*rows*columns这么多空间 ,无论是一维,二维,还是三维数组,最终都是线型的存储在内存中,问题的关键在于能不能通过matrix[i][j] 这样形式,使用下标能够正确的索引。

常见的错误写法如下:

int rows = 10;
	int columns = 5;

	int** matrix = (int**)malloc(rows*columns*sizeof(int));
	for (int i = 1; i < rows; ++i)
	{
		matrix[i] = matrix[0] + i*columns;
	}
	matrix[9][9] = 0;

这里的matrix[0]是分配空间的最开始四个字节,由于matrx的类型是int**,所以这四个字节此时被当做int*来解释了,不过由于这四个字节的内容未知,这就是错误的根源!



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值