2

我在这里做一些愚蠢的事情,我无法确切说明是什么:

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

我错过了什么?

谢谢

4

6 回答 6

9

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

于 2012-07-13T02:56:07.690 回答
1

dataAfrommain永远不会被初始化。data您传递给的指针init_data会立即被 . 返回的指针覆盖malloc

于 2012-07-13T02:50:47.747 回答
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.

于 2012-07-13T02:52:43.880 回答
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]);
于 2012-07-13T02:55:13.193 回答
1

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

第一个问题是它init_data需要 adouble**作为它的第一个参数,但是您传递的是 a double*** (check your compiler warnings)。由于init_data正在初始化它自己分配的内存,而不是初始化您在其他地方分配的内存块,您可以删除第一个参数并返回 a double**

您还为data. 你想要的是足够的内存dim_xdouble*不是 double. 您也可以使用sizeof(*data)(type of *datais double*) 而不是sizeof(double*).

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


由于这些s 中的每一个指向的内存块中都有dim_x double*s 和s ,因此您的第一个循环应该迭代到,而第二个循环应该迭代到.dim_y doubledouble*dim_xdim_y

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


另一个问题与printf格式说明符有关。%d是 for 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;
}
于 2012-07-13T03:13:59.117 回答
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);         
        }     
    } 
} 
于 2012-07-13T10:22:18.547 回答