0

C で 2 つの 3D 連続配列を作成する必要があります ( と で示されx0ていますx)。寸法は と である必要がx[size_tot_y][size_tot_x][size_tot_z]ありx0[size_tot_y][size_tot_x][size_tot_z]ます。私のコードは次のとおりです:

  double*** x;
  double** x_val2;

  double*** x0;
  double** x0_val2;

  x0 = malloc(size_tot_y*sizeof(double**));
  x0_val2 = malloc(size_tot_x*size_tot_y*size_tot_z*sizeof(double*));

  x = malloc(size_tot_y*sizeof(double**));
  x_val2 = malloc(size_tot_x*size_tot_y*size_tot_z*sizeof(double*));

  for(j=0;j<=size_tot_y-1;j++) {    
      x0[j] = &x0_val2[j*size_tot_x*size_tot_z];
      x[j] = &x_val2[j*size_tot_x*size_tot_z];
      }

  for(i=0;i<=size_tot_y-1;i++) {
      for(j=0;j<=size_tot_x-1;j++) {
          x0[i][j] = malloc(size_tot_z*sizeof(double));
      x[i][j] = malloc(size_tot_z*sizeof(double));
      }
     }

  for(i=0;i<=size_tot_y-1;i++) {
      for(j=0;j<=size_tot_x-1;j++) {
          x0[i][j] = x0_val2[i*j*size_tot_z];
      x[i][j] = x_val2[i*j*size_tot_z];
      }
     }     

エラーがどこにあるかわかりますか?

ありがとう

4

3 に答える 3

1

あなたのコードは私にはあまりにも複雑に思えます。ただ行う:

 double ***x;
 x = malloc(size_tot_y * sizeof(*x));
 for (i = 0; i < size_tot_y; i++) {
   x[i] = malloc(size_tot_x * sizeof(**x));
   for (j = 0; j < size_tot_x; j++) {
     x[i][j] = malloc(size_tot_z * sizeof(***x));
   }
 }

についても同じですx0。同じコードを2回記述する必要がないように、ルーチンでラップします。

編集

連続した配列の場合は、次のようにします。

 double *storage = malloc(size_tot_x * size_tot_y * size_tot_z * sizeof(*storage));
 double *alloc = storage;
 double ***x;
 x = malloc(size_tot_y * sizeof(*x));
 for (i = 0; i < size_tot_y; i++) {
   x[i] = malloc(size_tot_x * sizeof(**x));
   for (j = 0; j < size_tot_x; j++) {
     x[i][j] = alloc;
     alloc += size_tot_z;
   }
 }

それはあなたが本当にポインタが欲しいならです。そうでない場合は、すべてのメモリを割り当てて、自分でインデックスを作成します。

double *storage = malloc(size_tot_x * size_tot_y * size_tot_z * sizeof(*storage));
double get(const double *storage, int x, int y, int z) {
    return storage[(y * size_tot_x + x) * size_tot_z + z];
}
于 2012-10-04T21:38:47.803 に答える
0

私はほぼ1年前にCを始めたばかりで、あなたはこの男を少しも助けていません.

また、メモリの連続ブロックを使用して、奇妙な多次元オブジェクトであるテンソルを作成したいと考えていました。立方体の 3 つの直交面に印刷された 3 つの 3x3 マトリックスを考えてみてください。

C の大きな問題は、3D 配列 arr[number][column][row] を作成すると、「列 x 行」行列の「数」になると、メモリ ブロックが連続するが、順序が正しくないことです。 .

なぜ arr[2][4][4] などの配列を初期化するのか疑問に思ったことはありませんか?

int arr[2][4][4]=   
        {
            {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 16}
            },
            {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 16}
            },
        };

しかし、C はゼロからカウントを開始することは誰もが知っているので、行列をより大きな行列に埋め込み、それを囲むガベージ データと、完全にガベージ データの 3 番目の行列を作成します。ガベージデータを印刷する方法は次のとおりです。

#define COMPLEX 2
#define ROW 2
#define COLUMN 2
void L_print(int u[COMPLEX][ROW][COLUMN])
{
    int i,j,k;
    for(i=0;i<=COMPLEX;i++)
    {
        for(j=0;j<=ROW;j++)
        {
            for(k=0;k<=COLUMN;k++)
            {
                printf("%d ",u[i][j][k]);
            }
            printf("\n");
        }
        printf("\n");
    }
}

したがって、ガベージ マトリックスに埋め込まれた正しいデータが得られます。C はガベージ データ スロットをランダムなガベージ データで埋めているようです。それらはすべて '\0' などではありません。

そのため、行列のサイズを実行時に変更するためにポインターを使用したかったため、ポインターに基づいて操作の同型を作成する必要がありました。

ここで、ポインターを宣言し、それをマトリックスの最初のエントリに向けると:

ptr=&a[0][0][0];

そして、私は印刷します

 L_ptr_print(ptr,(2*4*4));  

これにより、適切なマトリックス エントリ (この場合は 2 つの 4x4 マトリックス) が吐き出されます。

しかし、配列がゼロからカウントを開始することは誰もが知っているため、配列 arr[2][4][4] には実際には sizeof(int) の大きい 3*5*5 の「スロット」があります。それでは、スロットを印刷しましょう!

L_ptr_print(ptr,(3*5*5));

得られるのは、最初の 32 エントリが適切に順序付けられたマトリックス エントリであるということです。次の 43 エントリは、行列 arr[2][4][4] を完全に出力したときに得られるガベージ データです。

したがって、3D 動的に割り当てられた連続配列を作成する最も簡単でエレガントな方法は、そもそも 3D にしないことではないと判断しました。

単純にポインタを malloc し、配列要素の数と同じサイズにします。したがって、32*sizeof(int) ポインターを malloc します。

int* ptr;
ptr=(int*)malloc(32*sizeof(int));

次に、配列の各要素をこのように、またはやりたい方法で入力します。

for(i=0;i<31;i++)
{
    *(ptr+i)=i+1;
}

これは 32 int を出力でき、わずか 32*sizeof(int) バイトです。これにより、ダブル ポインターとトリプル ポインターが不要になります。

または、既にマトリックスがある場合は、常に単一のポインターを各ブロックに手動で指すことができます。ポインターはメモリを占有せず、配列は占有し、ポインターはポイントするため、メモリのクリアについて心配する必要はありません。配列に。ただし、実行時に配列のサイズを変更することはできません。

于 2016-07-16T21:26:44.860 に答える
0

プロセス間で 2 次元配列を交換する MPI コード用の 3 次元連続配列が必要です。そのために、連続した配列を必要とする MPI_Sendrecv ルーチンを使用します。

@キース、あなたのソリューションはうまくいかないようです。

たとえば、このコードの 2D バージョンでは、次のように 2D 連続配列を作成しますx0

  x0 = malloc(size_tot_y*sizeof(double*));
  x0_vals = malloc(size_tot_x*size_tot_y*sizeof(double));

  for(j=0;j<=size_tot_y-1;j++) {
    x0[j] = &x0_vals[j*size_tot_x];
  }

3D に相当するものは何ですか?

于 2012-10-05T18:20:37.760 に答える