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

时间:2009-05-27 20:10:17

标签: c arrays dynamic

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

9 个答案:

答案 0 :(得分:74)

使用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的2D数组。因此,例如,如果您想要640 * 480阵列(图像的fe像素),请使用dimension1_max = 640,dimension2_max = 480.然后,您可以使用x[d1][d2]访问阵列其中d1 = 0..639,d2 = 0..479。

但搜索SO或Google也会发现其他可能性,例如in this SO question

请注意,在这种情况下,您的数组不会分配连续的内存区域(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);

答案 1 :(得分:73)

自C99起,C具有动态界限的2D数组。如果你想避免在堆栈上分配这样的野兽(你应该),你可以一次轻松地分配它们,如下所示

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

就是这样。然后,您可以轻松地使用它,就像用于A[i][j]之类的2D数组一样。不要忘记最后一个

free(A);

Randy Meyers撰写了一系列文章,解释variable length arrays (VLAs)

答案 2 :(得分:51)

基本

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

int ary1[5];

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

多维数组实现为数组(数组(of ...))。所以

float ary2[3][5];

声明一个由3个一维数组组成的数组,每个数组包含5个浮点数。现在ary2[0][0]是第一个数组的第一个元素,ary2[0][4]是第一个数组的最后一个元素,ary2[2][4]是最后一个数组的最后一个元素。 '89标准要求这些数据是连续的(我的K&amp; R 2nd编辑的第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是double的地址。你也不能使用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是一个局部变量,你不能返回它:数组的所有工作必须在你调用的函数中完成 it 电话。

指针数组

考虑一下:

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];声明的二维数组。

这个结构比二维数组更灵活(因为行的长度不必相同),但是访问它通常会更慢并且需要更多的内存(你需要一个位置来保存中间指针)。 / p>

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

算术

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

通过缩放器进行乘法以及相同等级的数组的加法和减法很容易:只需循环遍历元素并执行操作即可。内部产品同样直截了当。

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

答案 3 :(得分:9)

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

#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

您可以像对待任何2D数组一样对待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版本,那么您将需要做一些不同的事情。如果您需要在连续的块(如常规数组)中分配所有元素,那么您可以将内存分配为1D数组,并计算1D偏移量:

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);

答案 4 :(得分:0)

malloc会做的。

 int rows = 20;
 int cols = 20;
 int *array;

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

请参阅以下文章寻求帮助: -

http://courses.cs.vt.edu/~cs2704/spring00/mcquain/Notes/4up/Managing2DArrays.pdf

答案 5 :(得分:0)

以下是定义子例程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);
}

答案 6 :(得分:-1)

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

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 * 50整数或其他的块,并使用L宏进行访问,例如。

#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);

但除非你知道你对预处理器宏所做的事情的影响,否则这会更糟糕。

答案 7 :(得分:-1)

//使用new代替malloc,因为使用malloc会导致内存泄漏  `在此处输入代码

    int **adj_list = new int*[rowsize];       
    for(int i = 0; i < rowsize; ++i)    
    {

        adj_list[i] = new int[colsize];

    }

答案 8 :(得分:-2)

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));
        }