【问题标题】:C programming initialize 2D array dynamicallyC编程动态初始化二维数组
【发布时间】:2012-07-12 21:20:28
【问题描述】:

我在这里做了一些愚蠢的事情,我无法确定具体是什么:

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

我错过了什么?

谢谢

【问题讨论】:

  • 我发布了我的答案,你能检查一下它是否有效吗?

标签: c arrays memory pointers


【解决方案1】:

你在你的指针中犯了一些错误。您将&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 &lt; dim_x 而不是k &lt; dim_y。在当前情况下无关紧要,因为两个维度是相同的,但如果不是,则会导致问题。最后,您应该在 printf 中使用 %f 而不是 %d,因为双精度数的存储格式与整数不同,您可能会得到乱码而不是您想要的。

【讨论】:

  • 好的,我想我现在明白了。非常感谢
【解决方案2】:

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

【讨论】:

  • 我的想法是使用该函数对其进行初始化,然后对其进行操作。还是没有及时启动?
  • 然后你需要做类似*data = malloc ...
【解决方案3】:

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

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。

【讨论】:

    【解决方案4】:

    您没有在 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]);
    

    【讨论】:

      【解决方案5】:

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

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

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

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


      由于数据中有dim_xdouble*s 和dim_ydoubles 在每个double*s 指向的内存块中,你的第一个循环应该迭代到dim_x,并且你的仅次于dim_y。

      另外,在 C 中转换 malloc 的结果(转换 void*)是不必要的。这个网站上有一些答案会告诉你为什么不喜欢它。


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

      现在,如果您将代码添加到 free 您分配的内存并通过 valgrind 之类的东西运行您的程序,您会发现您不再在内存中做任何顽皮的事情。

      工作代码如下所示:

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

      【讨论】:

        【解决方案6】:

        第一个错误是您将&amp;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。这样我们就可以在控制脱离init_data函数后在main函数中显示它。我们还将存储指向双精度的指针。所以应该是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);         
                }     
            } 
        } 
        

        【讨论】:

          猜你喜欢
          • 2012-01-27
          • 2020-10-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-29
          相关资源
          最近更新 更多