C编程动态初始化2D数组

时间:2012-07-13 02:44:13

标签: c arrays memory pointers

我在做一些愚蠢的事情,我无法准确地指出:

 void init_data(double **data, int dim_x, int dim_y) {

    int i,j,k;

    data = (double **) malloc(sizeof(double) * dim_x);
    for (k = 0; k < dim_y; k++) {
        data[k] = (double *) malloc(sizeof(double) * dim_y);
    }

    for (i = 0; i < dim_x; i++) {
        for (j = 0; j < dim_y; j++) {
            data[i][j] = ((double)rand()/(double)RAND_MAX);
        }
    }
}

在main()中,我执行以下操作:

double **dataA;
int dim = 10; 
init_data(&dataA, dim, dim);

但是在那之后,当我尝试打印数据时,程序崩溃了:

int i,j;
    for(i=0;i<dim;i++)
        for(j=0;j<dim;j++)
            printf("%d\n", dataA[i][j]);

我错过了什么?

由于

6 个答案:

答案 0 :(得分:6)

你的指针犯了一些错误。您正在将&amp; dataA传递给init_data,因此参数类型应为*** double,而不是** double。你的第一个malloc也是初始化一个指针数组,而不是一个双精度数组,所以它应该是sizeof(double *)* dim_x。下面的代码应该有效。

void init_data(double ***data_ptr, int dim_x, int dim_y) {
  int i,j,k;
  double **data;
  data = (double **) malloc(sizeof(double *) * dim_x);
  for (k = 0; k < dim_x; k++) {
      data[k] = (double *) malloc(sizeof(double) * dim_y);
  }

  for (i = 0; i < dim_x; i++) {
      for (j = 0; j < dim_y; j++) {
          data[i][j] = ((double)rand()/(double)RAND_MAX);
      }
  }
  *data_ptr = data;
}

void main() {
  double **dataA;
  int dim = 10;
  init_data(&dataA, dim, dim);
  int i,j;
      for(i=0;i<dim;i++)
          for(j=0;j<dim;j++)
              printf("%f\n", dataA[i][j]);
}

你的第一个循环也应该具有条件k < dim_x而不是k&lt; dim_y。在当前情况下并不重要,因为两个维度都相同,但如果不是,则会引起问题。最后,你应该在你的printf中使用%f而不是%d,因为双打的格式与整数不同,你可能会得到比你想要的更多的胡言乱语。

答案 1 :(得分:1)

来自dataA的{​​{1}}永远不会被初始化。您传递给main的指针data会立即被init_data返回的指针覆盖。

答案 2 :(得分:1)

如果我想分配内存并初始化一块电路板,我会:

int
main(int argc, char *argv[])
{
  int xSize, ySize;
  int **board;

  xSize = ySize = 5;

  printf("X: %u; Y: %u\n", xSize, ySize);

  board = calloc(xSize, sizeof(int *));
  printf("%p\n", board);
  int **temp = board;

  for (i = 0; i < xSize; i++)
    {
      board[i] = calloc(ySize, sizeof(int));
      printf("%d %p\n", i, board[i]);
    }
  initializeBoard (board, xSize, ySize);
  temp = board;
  for (i = 0; i < xSize; i++)
    {
      free(*temp);
      (temp)++;
    }

  free(board);

  return 0;
}

因此,只需执行以下操作即可启用您的电路板:

void
initializeBoard (int **board, int xSize, int ySize)
{
  int x, y;

printf("----\n");
  for (x = 0; x < xSize; x++)
    {
      for (y = 0; y < ySize; y++)
    {
printf("%3d", board[x][y]);
      board[x][y] = 0;
    }
printf("\n");
    }
}

在您的情况下,请使用double代替int

答案 3 :(得分:1)

您没有在main()中设置dataA的值。

我会更改init_data的定义以返回指向新数据的指针。像这样:

double ** init_data(int dim_x, int dim_y) {
{
int i,j,k;

double **data = (double **) malloc(sizeof(double) * dim_x);
for (k = 0; k < dim_y; k++) {
    data[k] = (double *) malloc(sizeof(double) * dim_y);
}

for (i = 0; i < dim_x; i++) {
    for (j = 0; j < dim_y; j++) {
        data[i][j] = ((double)rand()/(double)RAND_MAX);
    }
}

return data;
}

然后在main()

double **dataA = init_data(10, 10);

int i,j;
for(i=0;i<dim;i++)
    for(j=0;j<dim;j++)
        printf("%d\n", dataA[i][j]);

答案 4 :(得分:1)

您的代码有几个问题,其中大部分都可以通过编译警告来轻松识别。

第一个问题是init_data期望double**作为它的第一个参数,但是你传递double*** (检查编译器警告)。由于init_data正在初始化它自己分配的内存,而不是初始化你在其他地方分配的内存块,你可以删除第一个参数并返回double**

您还为data分配了不足的内存量。你想要的是dim_x double*,{em>不 double的足够内存。您也可以使用sizeof(*data)*data类型为double*)而不是sizeof(double*)来实现这一目标。

data = malloc(sizeof(*data) * dim_x);


由于数据中有dim_x double*个,而dim_y s指向的内存块中有double double*,因此您的第一个循环应该是迭代到dim_x,你的第二个到dim_y

此外,不需要在C中投射malloc(投射void*)的结果。这个网站上有答案可以告诉你为什么你不喜欢它。


另一个问题与printf格式说明符有关。 %d用于int%f用于double(使用%lfscanf)。

现在,如果您将代码添加到free已分配的内存并通过 valgrind 之类的程序运行程序,您将看到您不再在内存中做任何顽皮的事情。< / p>

工作代码如下:

#include <stdio.h>
#include <stdlib.h>

double** init_data(int dim_x, int dim_y) {
   int i,j,k;
   double **data = malloc(sizeof(*data) * dim_x); /* hoping not NULL */

   for (k = 0; k < dim_x; k++) {
      data[k] = malloc(sizeof(**data) * dim_y);   /* hoping not NULL */
   }

   for (i = 0; i < dim_y; i++) {
      for (j = 0; j < dim_y; j++) {
         data[i][j] = ((double)rand()/(double)RAND_MAX);
      }
   }
   return data;
}

int main(void)
{
   double **dataA;
   int i, j, dim = 10; 
   dataA = init_data(dim, dim);

   for(i=0; i < dim; i++)
      for(j=0; j < dim; j++)
         printf("%f\n", dataA[i][j]);

   for (i = 0; i < dim; i++)
      free(dataA[i]);
   free(dataA);

   return 0;
}

答案 5 :(得分:1)

第一个错误是您将&dataA传递给函数init_data,但是在函数中,您接收的值为double **,它应该是double ***。因为你传递的是double **类型变量的指针。因此init_data函数原型应如下所示

void init_data(double ***data, int dim_x, int dim_y);

第二个错误在以下陈述中

data = (double **) malloc(sizeof(double) * dim_x); 

此声明应如下所示

*data = (double **) malloc(sizeof(double *) * dim_x); 

因为我们必须更新指针变量dataA。因此,在main函数控制出来后,我们将能够在init_data函数中显示它。而且我们将存储指向双精度的指针。所以它应该是sizeof(double *)

更新您的init_data功能,如下所示

void init_data(double ***data, int dim_x, int dim_y) 

{      
    int i,j,k;
    *data = (double **) malloc(sizeof(double *) * dim_x);
    for (k = 0; k < dim_y; k++) 
    {         
        ((*data) + k) = (double *) malloc(sizeof(double) * dim_y);     
    }      

    for (i = 0; i < dim_x; i++) 
    {         
        for (j = 0; j < dim_y; j++) 
        {             
            (((*data) +i) +j) = ((double)rand()/(double)RAND_MAX);         
        }     
    } 
}