概述
在C语言中动态的一维数组是通过malloc动态分配空间来实现的,动态的二维数组也可以通过malloc动态分配空间来实现。
实际上,C语言中没有二维数组,至少对二维数组没有直接的支持,取而代之的是“数组的数组”,二维数组可以看成是由指向数组的指针构成的数组。对于一个二维数组p[i][j],编译器通过公式*(*(p+i)+j)求出数组元素的值:
1、p+i 计算行指针。
2、*(P+i) 具体的行,是一个指针,指向该行首元素地址。
3、*(P+i)+j 得到具体元素的地址。
4、*(*(p+i)+j) 得到元素的值。
基于上述原理,我们可以通过分配一个指针数组,再对指针数组的每一个元素分配空间实现动态分配二维数组。
实现
下面是本人写的一个动态分配二维数组的实现,适用于任何类型的二维数组,可以直接使用。
类型定义和错误代码
typedef unsigned char MK_Byte; #define SUCCESS 0 /*No error*/ #define MFAILED 1 /*General failure*/ #define MNOMEMORY 2 /*Out of memory*/ 声明 //确保初始化 #define DeclareTwoDArray(ATYPE, iname) ATYPE ** iname = NULL //定义自己的malloc和free,确保内存正确操作 #define MKMALLOC(nsize) malloc(nsize) #define MKFREE(name) / if (NULL != name)/ free(name);/ name = NULL |
实现
int MKCreatArray(int nsize, int X, int Y, void *** parray) { void ** tdarray = NULL; MK_Byte * tmparray = NULL; int i = 0; *parray = NULL; //分配指针数组 if (!(tdarray = (void **)MKMALLOC(sizeof(MK_Byte *) * Y))) { return MNOMEMORY; } //分配实际数组空间 if (!(tmparray = (MK_Byte * )MKMALLOC(nsize * (X * Y)))) { MKFREE(tdarray); return MNOMEMORY; } //初始化内存 memset(tmparray, 0x00, nsize * (X * Y)); //指针数组赋值 for (i = 0; i < Y; i++) tdarray[i] = (tmparray + (i * X) * nsize); *parray = tdarray; return SUCCESS; } void MKFreeArray(void *** parray) { if (*parray) { MKFREE((*parray)[0]); MKFREE((*parray)); } } |
使用
void testTwoDArray() { //声明数组 DeclareTwoDArray(int, a); DeclareTwoDArray(float,b); //创建整型数组 MKCreatArray(sizeof(int), 3, 2, &a); a[1][2] = 10; a[0][1] = 23; printf("%d,%d/n",a[1][2],a[0][1]); //使用完一定要FREE MKFreeArray(&a); //重新分配数组 MKCreatArray(sizeof(int), 6, 6, &a); a[5][5] = 234; a[4][0] = 567; printf("%d,%d/n",a[5][5],a[4][0]); MKFreeArray(&a); //创建浮点数组 MKCreatArray(sizeof(float),2,2,&b); b[0][0] = 0.5f; b[1][1] = 0.006f; printf("%g,%g/n",b[0][0],b[1][1]); MKFreeArray(&b); } |
----------------------------------------------------------------------
其他讨论:
摘自:动态二维数组如何定义?
我在程序中需要使用一个动态的二维数组,行和列的值都需要传入。我在程序中使用了如下的方法:
#include "malloc.h"
...
double *t,**y;
t=(double *)calloc(r*c,sizeof(double)); //r,c是传入的行和列的值
y=(double **)calloc(r,sizeof(double *));
for(int i=0;i<r;i++) y[i]=&t[c*i];
...
结果在编译时没有问题,但运行时就回产生一个内存使用错误。
希望大家能够帮忙解决一下,或者有其他的解决方法也可以。谢谢!
---------------------------------------------------------------
可以这样使用二维数组:
假设前面已经定义了r行 和 c列
/*指向座标为(x,y)的单元的指针*/
#define M_pV(pHead, x, y) (pHead+c*y+x)
double *pArray=(double*)malloc(r*c*sizeof(double));
到时候可以这样用:
*M_pV(pArray, 1, 2)=9;
double temp=*M_pV(pArray, 1, 2);
---------------------------------------------------------------
用MFC的CArray模板为例,你也可以使用STL的vector等
做一个2维的动态int数组
typedef CArray<int,int> INTARRAY;
typedef CArray<INTARRAY,INTARRAY> Int2DArray;
---------------------------------------------------------------
一个二维数组,其实可以用一个一维指针来访问的。
如:int iMatrix[10][10];
int *piMatrix;
piMatrix = iMatrix; //数组名就是数组首地址
那么就有 *piMatrix[2*10+3] = iMatrix[2][3]
所以定义一个一维指针就可以了
int piMatrix;
piMatrix = (int*)malloc(r*c*sizeof(int));
for (i=0;i<r;i++)
for(j=0;j<c;j++)
piMatrix[i*r+j]
(当然,也可以定义一个2维数组,跟Kevin_qing()一样)
--------------------------------
摘自:动态分配二维数组的若干方法
动态分配二维数组的若干方法
动态分配二维数组,方法很多,在这里我说一下我想到的。针对二维数组两
个维的不同,可用不同的方法处理。
一、两维都固定:
这种是最简单,如下:
// 有点困惑的方法:
int (*a)[M][N]; // M、N 为常量
a = new int[1][10][20]; // 为什么要这样呢?
delete[] a;
// typedef 法,但一样的困惑
typedef int array_two[10][20];
array_two* a = new array_two[1]; // 还是多了“一维”
delete[] a;
唉,这个有点失败,使用时还要这样:(*a)[m][n],或者 a[0][m][n],这
还是二维的吗?没办法,只有另想办法了。
// 退一步,声明似乎少了一维 TYPE_1
int (*a)[N];
a = new int[M][N];
a[var_m][var_n] = 0;
delete[] a;
这样似乎不错,只是在声明时却少了一维,但使用起来简单,形式一样。
二、只有一维固定:
如果只有一维固定,分两种形式:[M][n] 和 [m][N],以后者较简单。对于
N 固定的,我们只要这样就可以了:
// [m][N] 型 TYPE_2
int (*a)[N];
a = new int[m][N];
a[var_m][var_n] = 0;
delete[] a;
这个看起来与 TYPE_1 很相似,比较二维数组作为函数的参数传递时,第一
维也是不重要的。看一下 new,出来的类型都是 int (*)[N]。
对于 [M][n] 这种,能过把下标交换一下,就可以利用 TYPE_2 这种了,确
实是不错。如果坚持用 [M][n] 的话,看一下有什么方法。
// [M][n] 型,直接的方法 TYPE_3
int* a[M];
for (int i = 0; i < M; ++i)
a[i] = new int[n];
a[var_m][var_n] = 0;
for (int i = M; i > 0;)
delete[] a[--i];
事实上,我们可以改进一下,只用一次 new:
// [M][n] 型,改进 TYPE_4
int* a[M];
a[0] = new int[M*n];
for (int i = 1; i < M; ++i)
a[i] = a[i-1] + n;
a[var_m][var_n];
delete[] a[0];
这样改进的好处是,减少 new 所带来的固有开销;如果失败,无需对前面
已分配的再 delete[]。当然,如果内存比较碎的话,那就没办法了。
三、二维都是动态确定:
二维都是动态确定的话,可以这样:
// [m][n],直接的方法 TYPE_5
int** a;
a = new (int*)[m];
for (int i = 0; i < m; ++i)
a[i] = new int[n];
a[var_m][var_n] = 0;
for (int i = m; i > 0;)
delete[] a[--i];
delete[] a;
类似改进 TYPE_3,我们也可以将 TYPE_5 改进:
// [m][n],改进 TYPE_6
int** a;
a = new (int*)[m];
a[0] = new int[m*n];
for (int i = 1; i < m; ++i)
a[i] = a[i-1] + n;
a[var_m][var_n] = 0;
delete[] a[0];
delete[] a;
好了,这就是我所想到的办法,当然你可以 std::vector 来搭建二维数组,
只是效率似乎没人满意。实际上,可以只分两种情况:最后一维确定,或不确定。
最后一维确定,只需一次分配;否则,一般要两次。
---------------------------------------------------------------
// [M][n] 型,改进 TYPE_4
int* a[M];
a[0] = new int[M*n];
for (int i = 1; i < M; ++i)
a[i] = a[i-1] + n;
a[var_m][var_n];
delete[] a[0];
这里似乎有些问题,是不是应该改成a[i] = a[i-1] + sizeof(int)*n;
---------------------------------------------------------------
有价值。
up
---------------------------------------------------------------
up
---------------------------------------------------------------
int (*a)[M][N]; // M、N 为常量
a = new int[1][10][20]; // 为什么要这样呢?
这里的a不应该是一个三维数组吗?不知道是楼主弄错了还是我理解得不对?
另外,用vector来构建二维数组我觉得没有什么不好,不知道为什么楼主认为效率不令人满意?
---------------------------------------------------------------
楼上的意见我认可
*a[][]逻辑上已经是三维了
至于你的typedef int array_two[10][20];
array_two* a = new array_two[1]; // 还是多了“一维”
这样定义了 array_two本身是二维数组,定义它的指针也应该是首先分配的是二维数组指针的空间
typedef 定义对象指针
有一个好处就是new的时候不会调用构造函数
class Object{...
}
typedef Object* OFun[1];
OFun = new Object[1];
---------------------------------------------------------------
学习...
---------------------------------------------------------------
mark
---------------------------------------------------------------
int (*a)[M][N]; // M、N 为常量
a = new int[1][10][20]; // 为什么要这样呢?
逻辑上是三维了,感觉就是用起来会方便一点吧,是作为指针来用了,作为一个二维指针,不过自己还没用到过这么困难的东西,看了是不少书,理论也不少了,可还是没实践,学习,
---------------------------------------------------------------
还有,我最推荐的是TYPE_5,这个东西可以搭建的就不只是m*n的数组了,而是一堆大小不同的一维数组的集合
------------------------------
摘自:动态申请二维数组
// allocate memory
p = (int**)malloc(row_x * sizeof(int*));
for (i=0; i<row_x; i++)
{
p[i] = (int*)malloc(row_y * sizeof(int));
}
// use them
for (i=0; i<row_x; i++)
for (j=0; j<row_y; j++)
p[i][j] = i+j;
// free allocated memory
for (i=0; i<row_x; i++)
{
free(p[i]);
}
free(p);
最后
以上就是默默星月为你收集整理的在C语言中实现动态分配二维数组的全部内容,希望文章能够帮你解决在C语言中实现动态分配二维数组所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复