簡體   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