我如何使用C中的动态多维数组?

有人知道如何使用C动态分配的多维数组? 那可能吗?

通过动态分配,使用malloc:

int** x; x = malloc(dimension1_max * sizeof(int*)); for (int i = 0; i < dimension1_max; i++) { x[i] = malloc(dimension2_max * sizeof(int)); } [...] for (int i = 0; i < dimension1_max; i++) { free(x[i]); } free(x); 

这将分配一个尺寸为dimension1_max * dimension2_max的二维数组。 所以,例如,如果你想要一个640×480的数组(像素的图像),使用dimension1_max = 640, dimension2_max = 480。然后,您可以使用x[d1][d2] ,其中d1 = 0访问数组。 639, d2 = 0 … 479。

但是搜索SO或Google也会揭示其他可能性,例如在这个SO问题中

请注意,在这种情况下,您的数组将不会分配连续的内存区域(640 * 480字节),这可能会导致存在此问题的函数出现问题。 所以为了让数组满足条件,用这个代替上面的malloc块:

 int** x; int* temp; x = malloc(dimension1_max * sizeof(int*)); temp = malloc(dimension1_max * dimension2_max * sizeof(int)); for (int i = 0; i < dimension1_max; i++) { x[i] = temp + (i * dimension2_max); } [...] free(temp); free(x); 

自C99以来,13年来,C具有动态范围的2D阵列。 如果你想避免这样的野兽被分配到堆栈(你应该),你可以轻松地一次性分配它们,如下

 double (*A)[n] = malloc(sizeof(double[n][n])); 

就是这样。 你可以很容易地使用它,因为你用于像A[i][j]这样的二维数组。 而且不要忘了最后一个

 free(A); 

兰迪·迈耶斯(Randy Meyers)写了一系列文章解释变长数组 (VLA) 。

基本

使用[]运算符声明和访问c中的数组。 以便

 int ary1[5]; 

声明一个由5个整数组成的数组。 元素从零开始编号,所以ary1[0]是第一个元素,而ary1[4]是最后一个元素。 注1:没有默认的初始化,所以数组占用的内存最初可能包含任何内容 。 注2: ary1[5]以未定义的状态访问内存(可能无法访问),所以不要这样做!

多维数组被实现为数组的数组(数组(…))。 所以

 float ary2[3][5]; 

声明一个包含5个浮点数的3个一维数组。 现在ary2[0][0]是第一个数组的第一个元素, ary2[0][4]是第一个数组的最后一个元素,而ary2[2][4]是最后一个数组的最后一个元素。 '89标准要求这些数据是连续的(K&R第2版第216页第A8.6.2节),但对于填充似乎是不可知的。

试图在多个维度上发挥作用

如果您在编译时不知道数组的大小,则需要动态分配数组。 这是很有吸引力的尝试

 double *buf3; buf3 = malloc(3*5*sizeof(double)); /* error checking goes here */ 

如果编译器不填充分配(在一维数组之间插入额外的空间),这应该工作。 一起走可能更安全:

 double *buf4; buf4 = malloc(sizeof(double[3][5])); /* error checking */ 

但无论哪种方式的诀窍来解除引用的时间。 你不能写buf[i][j]因为buf的类型是错误的。 你也不能使用

 double **hdl4 = (double**)buf; hdl4[2][3] = 0; /* Wrong! */ 

因为编译器期望hdl4是双hdl4地址的地址。 你也不能使用double incomplete_ary4[][]; 因为这是一个错误;

所以,你可以做什么?

  • 做自己的行和列算术
  • 在一个函数中分配和执行这个工作
  • 使用指针数组(机构qrdl正在谈论)

自己做数学

简单地计算每个元素的内存偏移,如下所示:

  for (i=0; i<3; ++i){ for(j=0; j<3; ++j){ buf3[i * 5 + j] = someValue(i,j); /* Don't need to worry about padding in this case */ } } 

在一个函数中分配和执行这个工作

定义一个将所需大小作为参数并按正常方式进行的函数

 void dary(int x, int y){ double ary4[x][y]; ary4[2][3] = 5; } 

当然,在这种情况下, ary4是一个局部变量,你不能返回它:数组的所有工作都必须在你调用的函数中完成。

一个指针数组

考虑这个:

 double **hdl5 = malloc(3*sizeof(double*)); /* Error checking */ for (i=0; i<3; ++i){ hdl5[i] = malloc(5*sizeof(double)) /* Error checking */ } 

现在hdl5指向一个指针数组,每个指针指向一个双精度数组。 很酷的是,你可以使用二维数组符号来访问这个结构— hdl5[0][2]得到第一行的中间元素—但这是一个不同的类型的对象,而不是由double ary[3][5];声明的二维数组double ary[3][5];

这个结构比二维数组更灵活(因为行不一定是相同的长度),但是访问它通常会比较慢,并且需要更多的内存(你需要一个容纳中间指针的地方)。

请注意,由于我没有设置任何警卫,所以您必须自己跟踪所有阵列的大小。

算术

c不支持矢量,矩阵或张量数学,你必须自己实现它,或者引入一个库。

通过缩放器进行乘法运算和对相同排序的数组进行加减运算是很容易的:只需循环遍历元素,并随时执行操作。 内在的产品同样是直截了当的。

外部产品意味着更多的循环。

如果你知道编译时的列数,那很简单:

 #define COLS ... ... size_t rows; // get number of rows T (*ap)[COLS] = malloc(sizeof *ap * rows); // ap is a *pointer to an array* of T 

你可以像任何二维数组一样对待ap

 ap[i][j] = x; 

完成后,将其解除分配

 free(ap); 

如果您在编译时不知道列的数量,但是您正在使用支持可变长度数组的C99编译器或C2011编译器,它仍然非常简单:

 size_t rows; size_t cols; // get rows and cols T (*ap)[cols] = malloc(sizeof *ap * rows); ... ap[i][j] = x; ... free(ap); 

如果你不知道编译时的列数,而且你正在使用一个不支持可变长度数组的C版本,那么你需要做一些不同的事情。 如果您需要将所有元素分配到连续块(如常规数组)中,则可以将内存分配为一维数组,并计算一维偏移量:

 size_t rows, cols; // get rows and columns T *ap = malloc(sizeof *ap * rows * cols); ... ap[i * rows + j] = x; ... free(ap); 

如果您不需要内存连续,您可以按照两步分配方法:

 size_t rows, cols; // get rows and cols T **ap = malloc(sizeof *ap * rows); if (ap) { size_t i = 0; for (i = 0; i < cols; i++) { ap[i] = malloc(sizeof *ap[i] * cols); } } ap[i][j] = x; 

由于分配是一个两步过程,所以释放也需要分两步:

 for (i = 0; i < cols; i++) free(ap[i]); free(ap); 

malloc会做的。

  int rows = 20; int cols = 20; int *array; array = malloc(rows * cols * sizeof(int)); 

请参阅下面的文章寻求帮助: –

~cs2704/spring00/mcquain/Notes/4up/Managing2DArrays.pdf

这里是工作代码,它定义了一个子程序make_3d_array ,在每个维度中分配一个包含N1N2N3元素的多维3D数组,然后用随机数填充它。 您可以使用符号A[i][j][k]来访问其元素。

 #include <stdio.h> #include <stdlib.h> #include <time.h> // Method to allocate a 2D array of floats float*** make_3d_array(int nx, int ny, int nz) { float*** arr; int i,j; arr = (float ***) malloc(nx*sizeof(float**)); for (i = 0; i < nx; i++) { arr[i] = (float **) malloc(ny*sizeof(float*)); for(j = 0; j < ny; j++) { arr[i][j] = (float *) malloc(nz * sizeof(float)); } } return arr; } int main(int argc, char *argv[]) { int i, j, k; size_t N1=10,N2=20,N3=5; // allocates 3D array float ***ran = make_3d_array(N1, N2, N3); // initialize pseudo-random number generator srand(time(NULL)); // populates the array with random numbers for (i = 0; i < N1; i++){ for (j=0; j<N2; j++) { for (k=0; k<N3; k++) { ran[i][j][k] = ((float)rand()/(float)(RAND_MAX)); } } } // prints values for (i=0; i<N1; i++) { for (j=0; j<N2; j++) { for (k=0; k<N3; k++) { printf("A[%d][%d][%d] = %f \n", i,j,k,ran[i][j][k]); } } } free(ran); } 

没有办法一次性分配整个事情。 相反,创建一个指针数组,然后,为每个指针创建它的内存。 例如:

 int** array; array = (int**)malloc(sizeof(int*) * 50); for(int i = 0; i < 50; i++) array[i] = (int*)malloc(sizeof(int) * 50); 

当然,您也可以将数组声明为int* array[50]并跳过第一个malloc,但需要第二个集合才能动态分配所需的存储空间。

可以通过一种方式来分配它,但它需要一个自定义的查找函数,但是以这样的方式编写它将始终工作可能会很烦人。 一个例子可以是L(arr,x,y,max_x) arr[(y)*(max_x) + (x)] ,然后malloc一个50 *

 #define L(arr,x,y,max_x) arr[(y)*(max_x) + (x)] int dim_x = 50; int dim_y = 50; int* array = malloc(dim_x*dim_y*sizeof(int)); int foo = L(array, 4, 6, dim_x); 

但是,除非你知道你使用预处理器宏做什么的效果,否则这是非常难看的。

 int rows, columns; /* initialize rows and columns to the desired value */ arr = (int**)malloc(rows*sizeof(int*)); for(i=0;i<rows;i++) { arr[i] = (int*)malloc(cols*sizeof(int)); } 

为什么同事们都没有透露一个事实,那就是C领域没有确切的解决方案? 但只有在C + +( 确切地说,我的意思是上述和其他网站的解决方案不同于真正的 C多维数组:附加实体,所以额外的内存等)。

在C ++中,你必须实现(只是几行代码):

 typedef double T; class Matrix2D { public: Matrix2D(int, int); ~Matrix2D(); T* operator[](int); private: T* const memory; const int rows; const int cols; }; Matrix2D::Matrix2D(int r, int c) : rows(r), cols(c), memory(new T[r*c]) {} Matrix2D::~Matrix2D() { delete[] memory; } T* Matrix2D::operator[](int row) { return memory + cols*row;} 

这就是那些使用这样的代码的人: a[i][j]

但是对于类( Matrix2D )缺少双指针算术的C Matrix2D数组的精确相似性,可以这样使用: (*(a+i))[j] 。 这并不难:用算术和解引用操作符实现内部的“双重指针”。 但是我宁愿为了这种目的而实现一些迭代器(从一行到另一行)。

超过2个维度? 您只需要实现(n-1)维的相应operator[]...[]的内部类。 唉,例行公事