11

2D 配列を動的に割り当て/割り当て解除するア​​ルゴリズムについては知っていますが、3D 配列についても同じことはよくわかりません。
この知識と少しの対称性を使用して、次のコードを思い付きました。
(コーディング中に 3D で視覚化するのに苦労しました)。

正しさについてコメントし、より良い代替案 (効率的または直感的に) を提案してください。
また、arr2D[2][3] や arr3D[2][3][2] などの静的配列と同様に、これらの 2D 配列と 3D 配列の両方に正常にアクセスできると思います
。右?

2D のコード

//allocate a 2D array
int** allocate2D(int rows,int cols)
{
    int **arr2D;
    int i;

    arr2D = (int**)malloc(rows*sizeof(int*));
    for(i=0;i<rows;i++)
    {
        arr2D[i] = (int*)malloc(cols*sizeof(int));
    }
}

//deallocate a 2D array
void deallocate2D(int** arr2D,int rows)
{
    int i;

    for(i=0;i<rows;i++)
    {
        free(arr2D[i]);
    }

    free(arr2D);
}  

3D のコード

//allocate a 3D array
int*** allocate3D(int l,int m,int n)
{
int ***arr3D;
int i,j,k;

arr3D = (int***)malloc(l * sizeof(int **));

for(i=0;i<l;i++)
{
    arr3D[i] = (int**)malloc(m * sizeof(int*));
    for(j=0;j<m;j++)
    {
        arr3D[i][j] = (int*)malloc(n*sizeof(int));
    }
}

return arr3D;
}

//deallocate a 3D array
void deallocate3D(int arr3D,int l,int m)
{
    int i,j;

    for(i=0;i<l;i++)
    {
        for(int j=0;j<m;j++)
        {
            free(arr3D[i][j]);
        }
        free(arr3D[i]);
    }
    free(arr3D);
}
4

4 に答える 4

11

1 つの配列を割り当てて、個々のインデックスを計算することもできます。これにより、必要なアロケーター呼び出しが少なくなり、断片化が減り、キャッシュの使用が改善されます。

typedef struct {
  int a;
  int b;
  int* data;
} Int2d;

Int2d arr2d = { 2, 3 };
arr2d.data = malloc(arr2d.a * arr2d.b * sizeof *arr2d.data);

arr2d[r][c]になりましarr2d.data[r * arr2d.b + c]た。解放は単一の free() 離れています。おまけとして、動的配列のサイズを常に手元に置いておくことができます。

3D への外挿:

typedef struct {
  int a;
  int b;
  int c;
  int* data;
} Int3d;

Int3d arr3d = { 2, 3, 4 };
arr3d.data = malloc(arr3d.a * arr3d.b * arr3d.c * sizeof *arr3d.data);

//arr3d[r][c][d]
// becomes:
arr3d.data[r * (arr3d.b * arr3d.c) + c * arr3d.c + d];

これらのインデックス操作 (およびそのための (解放) 割り当て) を別の関数またはマクロにカプセル化する必要があります。

(r、c、および d の名前の方が適切である可能性があります。行、列、および深さを意味していました。a、b、および c は対応する次元の制限ですが、n1、n2、n3 のような名前を好む場合があります。配列を使用することもできます。)

于 2009-12-01T07:03:54.037 に答える
4

arr3d は、単なる int ではなく、トリプル ポインターである必要があります。それ以外の場合は問題ありません:

void deallocate3D(int*** arr3D,int l,int m)
{
    int i,j;

    for(i=0;i<l;i++)
    {
        for(int j=0;j<m;j++)
        {
                free(arr3D[i][j]);
        }
        free(arr3D[i]);
    }
    free(arr3D);
}

arr3D はポインター ツー ポインター ツー ポインターであるため、arr3D[i] はポインター ツー ポインターであり、arr3D[i][j] は単なるポインターです。最初にループ内の最も低い次元を解放してから、arr3D 自体が解放されるまで次元を上げていくのが正しいです。

mallocまた、指定された型の sizeof を暗黙的に指定する方が慣用的です。それ以外の:

  arr3D[i] = (int**)malloc(m * sizeof(int*));

成功する:

  arr3D[i] = (int**)malloc(m * sizeof(*arr3D[i]));

はい、そのような動的に割り当てられた多次元配列は、静的に割り当てられた多次元配列と同じようにアクセスできます。

于 2009-12-01T06:42:56.697 に答える
1

以下のコードを確認できます。

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

void main()
{
    //  Array 3 Dimensions
    int x = 4, y = 5, z = 6;

    //  Array Iterators
    int i, j, k;

    //  Allocate 3D Array
    int *allElements = malloc(x * y * z * sizeof(int));
    int ***array3D = malloc(x * sizeof(int **));

    for(i = 0; i < x; i++)
    {
        array3D[i] = malloc(y * sizeof(int *));

        for(j = 0; j < y; j++)
        {
            array3D[i][j] = allElements + (i * y * z) + (j * z);
        }
    }

    //  Access array elements
    for(i = 0; i < x; i++)
    {
        printf("%d\n", i);

        for(j = 0; j < y; j++)
        {
            printf("\n");

            for(k = 0; k < z; k++)
            {
                array3D[i][j][k] = (i * y * z) + (j * z) + k;
                printf("\t%d", array3D[i][j][k]);
            }
        }

        printf("\n\n");
    }

    //  Deallocate 3D array
    free(allElements);
    for(i = 0; i < x; i++)
    {
        free(array3D[i]);
    }
    free (array3D);
}

詳細については、このリンク3d 配列を参照してください

于 2012-12-29T06:22:40.253 に答える
0

これは質問のアイデアのバージョンですが、他の回答に触発されたmallocを1つだけ使用しています。角括弧を直感的に使用でき、クリーニングも簡単です。コンパイラの実装に固有の仮定を行わないことを願っています。

int main(int argc, char *argv[])
{
  int **array, i, j;
  array = allocate2d(3, 4);
  for (i = 0; i < 3; i++)
  {
    for (j = 0; j < 4; j++)
    {
      array[i][j] = j + i + 1;
    }
  }
  for (i = 0; i < 3; i++)
  {
    for (j = 0; j < 4; j++)
    {
      printf("array[%d][%d] = %d\n", i, j, array[i][j]);
    }
  }
  free(array);
  return EXIT_SUCCESS;
}

int **allocate2d(int x, int y)
{
  int i;
  int **array = malloc(sizeof(int *) * x + sizeof(int) * x * y);
  for (i = 0; i < x; i++)
  {
    array[i] = ((int *)(array + x)) + y * i;
  }
  return array;
}
于 2013-12-18T15:08:10.890 に答える