c - 将 malloc 用于结构的多维数组

标签 c arrays struct malloc

这可能是一个基本问题,但我想为结构的 3 维数组分配内存。 我正在尝试从文件中读取 double 并希望存储在结构中。第一行是 block 号(这里不相关,因为它总是1),第二行分别表示X,Y和Z坐标中的网格点数。在这种情况下,X 方向有 10 个点,Y 方向有 5 个点,Z 方向有 1 个点。从第三行开始,是每个点的 X、Y、Z 坐标,它们是我想要读取的 double 。首先是所有 X 分量(即 10*5*1 x 坐标,然后是类似的 Y 和 Z)。文件格式是这样的:

      1
      10        5        1
  0.000000e+00   1.111111e+00   2.222222e+00   3.333333e+00 
  4.444445e+00   5.555555e+00   6.666667e+00   7.777778e+00 
  8.888889e+00   1.000000e+01   0.000000e+00   1.111111e+00 
  2.222222e+00   3.333333e+00   4.444445e+00   5.555555e+00 
  6.666667e+00   7.777778e+00   8.888889e+00   1.000000e+01 
  0.000000e+00   1.111111e+00   2.222222e+00   3.333333e+00 
  4.444445e+00   5.555555e+00   6.666667e+00   7.777778e+00 
  8.888889e+00   1.000000e+01   0.000000e+00   1.111111e+00 
  2.222222e+00   3.333333e+00   4.444445e+00   5.555555e+00 
  6.666667e+00   7.777778e+00   8.888889e+00   1.000000e+01 
  0.000000e+00   1.111111e+00   2.222222e+00   3.333333e+00 
  4.444445e+00   5.555555e+00   6.666667e+00   7.777778e+00 
  8.888889e+00   1.000000e+01...and so on...

我可以读取前 4 个整数,因此我知道我希望存储数据的点数。然后我使用 malloc 函数分配内存并将数据存储在变量中。当我执行程序时,它读取整数但无法读取 double 。我犯了什么错误?

这是我的代码:

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

typedef struct{
    double x,y,z;
}Mesh;

int main(void)
{
    int nblocks, IMAX, JMAX, KMAX;

    Mesh ***grid;

    FILE *mesh = fopen("test.x","r");

    fscanf(mesh,"%i %i %i %i",&nblocks,&IMAX,&JMAX,&KMAX);
    printf("%i %i %i %i\n",nblocks,IMAX,JMAX,KMAX);

    grid = malloc(sizeof(Mesh)*nblocks*IMAX*JMAX*KMAX);

    fscanf(mesh,"%lf",&grid[0][0][0].x);
    printf("%lf\n",grid[0][0][0].x);

    fclose(mesh);

    return 0;
}

程序在编译时没有给出任何错误,但它没有读/写我存储在结构的 x 变量中的变量。 (如果可行,我可以将其放入循环中以读取我未在此处完成的所有值。)

如果我在读入 IMAX,JMAX,KMAX 后定义 Mesh grid[IMAX][JMAX][KMAX],我会得到正确的输出。但想知道指针的工作方式。

谢谢, 普拉纳夫

最佳答案

问题是您将网格定义为指向结构指针的指针,但您认为您有一个连续元素的三维数组。

错误说明

以下数组:

Mesh array[10][5][1];   // what you would like to manage dynamically

会像这样存储在内存中:

+----+----+----+----+----+----+----+----+----+----+----+----+-----
|A000|A010|A020|A020|A030|A040|A100|A110|A120|A120|1030|A140|....
+----+----+----+----+----+----+----+----+----+----+----+----+-----

但是下面的指针指向指针

Mesh ***grid;           // How you decladed it 

就像这样管理:

grid-->  +--+--+--+--+--+--+--+
         | 0| 1| 2|........| 9|   some pointers to "pointers to struct"
         +--+--+--+--+--+--+--+
   grid[0] |
           +--->  +--+--+------+
                  | 1| 2| .... |   some pointers to struct 
                  +--+--+------+
         grid[0][0] |
                    +--->  +--+--+------+
                           | 1| 2| .... |   some struct 
                           +--+--+------+
               grid[0][0][0] |
                             +--->  +----+----+----+----
                                    |A000|A010|A020|... some struct  
                                    +----+----+----+----

您的 malloc() 分配了一组连续的 IMAX*JMAX*KMAX 结构元素。实际上,它就像一个一维数组,因为 malloc() 和您的编译器对维度及其各自的大小一无所知。

但是当您编写 grid[0] 时,您的代码会查看 grid 指向的地址并期望在那里找到一个指针(但它只是未初始化的结构)等等。所以你可能会在内存中的一个随机位置写入并得到一个段错误。

解决方案

您必须将网格作为结构的一维数组进行管理,并在您的代码中明确组织索引。

所以声明:

Mesh *grid; 

每当您想到网格的元素 [i][j][k] 时,请写:

grid[(i*JMAX+j)*KMAX+k]  

杂项说明:

您可以使用 calloc(IMAX*JMAX*KMAX, sizeof(Mesh)) 因为它清楚地表明它是一个数组,并且内存块设置为 0。

顺便说一下,(可能你的真实代码中已经有了它)作为反射总是检查分配是否成功,并在你不再需要它时预见一个 free() 。

关于c - 将 malloc 用于结构的多维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25512863/

相关文章:

c - arm 链接器在函数调用中使用的 'veneer' 是什么?

javascript - 按单词对 JavaScript 数组进行排序

java - 如何获得此 double 组以进行打印而不会出现错误?

C:sha256 哈希函数在结构体数组的字段中输出,导致将结构体内容写入磁盘时崩溃

C 指针、结构和 fwrite

c++ - 程序崩溃 - 除以 0

c - C程序中的运算符值评估问题

c - Linux c 套接字数据处理

c - 如何使用自定义函数 split() 将句子拆分为单个单词?

c++ - 澄清 C++ 结构中数据类型的析构函数要求