繁体   English   中英

使用malloc用于结构的多维数组

[英]using malloc for multidimensional array of struct

这可能是一个基本问题,但我想为结构的3维数组分配内存。 我正在尝试从文件中读取双打,并希望存储在struct中。 第一行是程序段号(此处无关紧要,因为它始终为1),第二行分别表示X,Y和Z坐标中的网格点数。 在这种情况下,X指向10,Y指向5,Z方向指向1。 从第三行开始,是每个点的X,Y,Z坐标,这是我想读取的双精度数。 首先是所有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函数分配内存并将数据存储在变量中。 当我执行程序时,它将读取整数,但无法读取双精度数。 我正在犯什么错误?

这是我的代码:

#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] 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()。

您有一个四维数组,而不是三个。 尺寸为:

  1. nblocks
  2. IMAX
  3. JMAX
  4. KMAX

因此, grid的类型必须是Mesh**** ,而不是Mesh***

Mesh ****grid;

您为grid分配内存的代码必须为:

grid = malloc(nblocks * (sizeof *grid));
for ( block = 0; block < nblocks; ++block )
{
   grid[block] = malloc(IMAX * (sizeof *grid[0]));
   for ( i = 0; i < IMAX ; ++i )
   {
      grid[block][i] = malloc(JMAX * (sizeof *grid[0][0]));
      for ( j = 0; j < JMAX ; ++j )
      {
         grid[block][i][j] = malloc(KMAX * (sizeof *grid[0][0][0]));
      }
   }
}

现在,您可以使用以下方法访问网格数据:

grid[block][index][jindex][kindex]

这些是有效用法:

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

一个简单的选择是编写:

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

然后访问项目:

grid[block_num][i][j][k] = 5;

您在注释中指出,由于nblocks始终为1 ,因此实际上并不需要nblocks ,在这种情况下,您可以执行以下操作:

Mesh (*grid)[JMAX][KMAX] = malloc( IMAX * sizeof *grid );
// ...
grid[i][j][k] = 5;

从C99开始,允许数组维不是编译时常量。 1个

注意习惯用法ptr = malloc(N * sizeof *ptr); ,这保证了我们分配ptr指向的任何类型的N ,因此即使ptr的类型很复杂,我们也可以确保分配了正确的字节数。


1此功能在C99中是必需的,但在C11中已更改为可选功能。 如果您使用的是符合C11的编译器,但没有VLA(我不知道任何编译器),则必须使用其他解决方案之一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM