【问题标题】:Reading 2d array from binary file and return the pointer this array (in C)从二进制文件中读取二维数组并返回该数组的指针(在 C 中)
【发布时间】:2016-02-24 10:23:05
【问题描述】:

我正在尝试编写一个函数,该函数返回从二进制文件读取的二维数组的指针。虽然我编译没有错误,但当我尝试打印数组的元素之一时,总是会出现分段错误。这是我的代码:

double ** readArray(int rows, int cols)
{
   int i;
   double **myArray=malloc(rows*sizeof(double*));
   if (myArray){ 
      for (i=0; i < rows; i++)
      {
        myArray[i]=malloc(cols*sizeof(double));
      }
   }        

   FILE *data;
   data=fopen("matrix.bin", "rb");
   fread(myArray,sizeof(double),rows*cols,data);

   return myArray; 
}

int main ()
{
  int cols = 7;
  int rows = 15;
  double **myArray=readArray(rows, cols);
  printf("%f\n", myArray[1][0]);
  return 0; 
}

【问题讨论】:

  • 你忘了free()你malloc()'ed
  • myArray 不是一个连续的内存区域,您进行的每个分配都可以返回一个指向可用空间中任何位置的指针。参见例如this old answer of mine 用于数组数组和指向指针“矩阵”的指针之间的区别。
  • 查看C FAQ section 6.16 并使用第二种方法来连续分配内存。如果您可以确保内存是连续的,您可以像您的代码一样使用fread() 读取整个文件。但也可以考虑使用mmap()

标签: c arrays pointers fread


【解决方案1】:

问题是您的代码中没有二维数组。指针对指针查找表的东西不是二维数组。它是散布在堆中随机位置的 [rows] 段数。因此,它也很慢。

此外,您应该将内存分配和算法分开。

改为这样做:

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

void* allocArray (int rows, int cols)
{
  return malloc( sizeof(double[rows][cols]) ); // allocate 1 2D-array
}

void readArray (int rows, int cols, double array[rows][cols])
{
   FILE *data;
   data=fopen("matrix.bin", "rb");
   fread(array, sizeof(double[rows][cols]), 1, data); // read 1 2D-array
}

int main ()
{
  int cols = 7;
  int rows = 15;
  double (*myArray)[cols] = allocArray(rows, cols);

  readArray(rows, cols, myArray);

  printf("%f\n", myArray[1][0]);

  free(myArray); // free 1 2D-array
  return 0; 
}

之所以使用特殊声明 double (*myArray)[cols] 而不是更符合逻辑的 double (*myArray)[rows][cols],是因为我们希望避免不方便的数组指针取消引用语法。 (*myArray)[1][0] 不易阅读。因此,与其声明指向 2D 数组的数组指针,不如声明指向 1D 数组的数组指针,然后在该数组指针上使用指针索引。对于任何指针,any_pointer[n] 给出指向的项目编号 n。数组指针没有区别,所以你得到一维数组编号 n。

【讨论】:

  • 非常感谢,您的解释太好了!
【解决方案2】:

您的fread() 调用正在覆盖您痛苦设置的所有指针。

您需要一次读取一行,并使用设置指针存储到:

for(size_t i = 0; i < rows; ++i)
  fread(myArray[i], cols * sizeof *myArray[i], data);

当然,在进行 I/O 和内存分配时,您也应该检查返回值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    相关资源
    最近更新 更多