如何动态分配2d数组?为什么?

时间:2014-10-06 20:27:06

标签: c arrays pointers multidimensional-array int

对于我的任务,我在程序中要做的一件事就是动态分配一个2D数组。 我无法弄清楚如何做或为什么。

这就是我现在所拥有的。

   size = atoi(argv[1]);
   int Pond[size][size];
   int i, j;
   for(i = 0; i < size; i ++){
      for(j = 0; j < size; j++){
        Pond[i][j]=0;
      }
   }

我找到了这样做的答案,但我无法弄清楚如何访问每一列或每行。

int **Pond;
Pond = (int**)malloc(size * sizeof(int*));
for (i = 0; i < size; i++) {
    Pond[i] = (int *) malloc(size * sizeof(int));

2 个答案:

答案 0 :(得分:4)

正确使用C&#39的强大数组类型语法如下所示:

int (*Pond)[size] = malloc(size * sizeof(*Pond));

这是分配的原因。之后,Pond中的元素可以像这样访问:

for(int y = 0; y < size; y++) {
    for(int x = 0; x < size; x++) {
        Pond[y][x] = 0;
    }
}

当然还有释放:

free(Pond);

它并不简单。

答案 1 :(得分:2)

[]运算符对指针的处理方式与对数组表达式的处理方式非常相似,因此无论您如何分配,都要使用Pond[i][j]来访问特定元素(除非您已分配)它作为一维数组,如dom0所示。)

如果在编译时已知行数和列数,则这是最简单的:

#define M ... // rows
#define N ... // columns

int (*Pond)[N] = malloc ( sizeof *Pond * M);
...
Pond[i][j] = x;
...
free( Pond );

变量Pond类型是&#34;指向N的指针 - int&#34;的元素数组。 表达式 *Pond的类型是&#34; int&#34;的N元素数组。所以sizeof *Pond给出了Nint的元素数组中的字节数;我们将其乘以M以获得数组所需的总字节数。

由于a[i]被评估为*(a + i),因此[]运算符在指针表达式上的工作方式与在数组表达式 1 上的工作方式相同;也就是说,您可以像使用常规2D数组一样使用Pond[i][j]

如果直到运行时才知道行数和列数,但您使用的是C99编译器或支持可变长度数组的C2011编译器,那么它很漂亮大致相同:

size_t n, m;
/**
 * get values of n and m
 */
int (*Pond)[n] = malloc( sizeof *Pond * m );
...
Pond[i][j] = x;
...
free( Pond );

与上述相同,只是mn在运行时才知道。在这两种情况下,动态分配的数组都是连续的(所有行在内存中都相邻)。

                +---+
          Pond: |   | ---+
                +---+    |
                 ...     |
                +---+    |
    Pond[0][0]: |   | <--+
                +---+
    Pond[0][1]: |   |
                +---+
                 ...
                +---+
  Pond[0][n-1]: |   |
                +---+
    Pond[1][0]: |   |
                +---+
    Pond[1][1]: |   |
                +---+
                 ...
                +---+
  Pond[m-1][0]: |   |
                +---+
  Pond[m-1][1]: |   |
                +---+
                 ...
                +---+
Pond[m-1][n-1]: |   |
                +---+

如果直到运行时才知道行数和列数,并且您使用的是不支持VLA的编译器,则根据您是否希望数组是连续的,您有两种选择。

如果阵列不必连续,您可以使用两步分配方法:

size_t n, m;
/**
 * get values for n and m
 */
int **Pond = malloc( sizeof *Pond * m ); // allocate m rows of pointer to int
if ( Pond )
{
  for ( size_t i = 0; i < m; i++ )
  {
    Pond[i] = malloc( sizeof *Pond[i] * n ); // allocate n columns of int for each row
  }
}

在这种情况下,Pond是指向int的指针;它最终会指向int的一维指针数组;这些指针中的每一个都将指向int的一维数组,类似于以下内容:

              +---+
        Pond: |   | ---+
              +---+    |
                       |
                +------+
                |
                V  
              +---+          
     Pond[0]: |   | ------------+ 
              +---+             |
     Pond[1]: |   | ---------+  |
              +---+          |  |
     Pond[2]: |   |          |  |  
              +---+          |  |
               ...           |  |
              +---+          |  |
   Pond[m-1]: |   |          |  | 
              +---+          |  |
                             |  |
              +---+          |  |
  Pond[0][0]: |   | <--------|--+
              +---+          |
  Pond[0][1]: |   |          |
              +---+          |
               ...           |
              +---+          |
Pond[0][n-1]: |   |          |
              +---+          |
                             |
              +---+          |
  Pond[1][0]: |   | <--------+
              +---+
  Pond[1][1]: |   |
              +---+
               ...
              +---+
Pond[1][n-1]: |   |
              +---+

但是因为Pond[i][j]被评估为*(*(Pond + i) + j),所以它仍然有效。

请注意,由于这是一个两步分配过程,因此重新分配还需要两个步骤:

for ( size_t i = 0; i < m; i++ )
  free( Pond[i] );
free( Pond );

如果数组确实需要连续,那么您必须将内存分配为一维数组并手动计算索引:

int *Pond = malloc( sizeof *Pond * m * n );
...
Pond[ i * m + j ] = x;
...
free( Pond );

<小时/> 1。在大多数情况下,数组表达式将被转换或&#34;衰减&#34;到指针表达式,所以下标实际上是在指针表达式上工作。