Cで関数の引数として多次元配列を渡す

配列の次元を個別のパラメーターとして使用して、最初の要素への明示的なポインターを渡します。たとえば、任意のサイズの int の 2 次元配列を処理するには:

void func_2d(int *p, size_t M, size_t N)
{
  size_t i, j;
  ...
  p[i*N+j] = ...;
}

これは

と呼ばれます
...
int arr1[10][20];
int arr2[5][80];
...
func_2d(&arr1[0][0], 10, 20);
func_2d(&arr2[0][0], 5, 80);

高次元の配列にも同じ原則が適用されます:

func_3d(int *p, size_t X, size_t Y, size_t Z)
{
  size_t i, j, k;
  ...
  p[i*Y*Z+j*Z+k] = ...;
  ...
}
...
arr2[10][20][30];
...
func_3d(&arr[0][0][0], 10, 20, 30);

これは、任意のデータ型で実行できます。単純にポインターツーポインターにします:

typedef struct {
  int myint;
  char* mystring;
} data;

data** array;

ただし、変数を malloc する必要があり、少し複雑になることを忘れないでください:

//initialize
int x,y,w,h;
w = 10; //width of array
h = 20; //height of array

//malloc the 'y' dimension
array = malloc(sizeof(data*) * h);

//iterate over 'y' dimension
for(y=0;y<h;y++){
  //malloc the 'x' dimension
  array[y] = malloc(sizeof(data) * w);

  //iterate over the 'x' dimension
  for(x=0;x<w;x++){
    //malloc the string in the data structure
    array[y][x].mystring = malloc(50); //50 chars

    //initialize
    array[y][x].myint = 6;
    strcpy(array[y][x].mystring, "w00t");
  }
}

構造体の割り当てを解除するコードは似ています。malloc したすべてのものに対して free() を呼び出すことを忘れないでください。 (また、堅牢なアプリケーションでは、malloc() の戻りを確認する必要があります)。

これを関数に渡したいとしましょう。おそらく、データ構造のポインターへのポインターではなく、データ構造を操作したいので、ダブル ポインターを引き続き使用できます。

int whatsMyInt(data** arrayPtr, int x, int y){
  return arrayPtr[y][x].myint;
}

この関数を次のように呼び出します:

printf("My int is %d.\n", whatsMyInt(array, 2, 4));

出力:

My int is 6.

関数を次のように宣言できます:

f(int size, int data[][size]) {...}

その後、コンパイラがすべてのポインタ演算を行います。

寸法のサイズはに表示する必要があることに注意してください 配列自体。

GNU C では、引数宣言の転送が可能です (配列の後に次元を渡す必要がある場合):

f(int size; int data[][size], int size) {...}

最初の次元は、引数として渡すこともできますが、C コンパイラには役に立ちません (sizeof 演算子であっても、引数として渡された配列に適用すると、常に最初の要素へのポインターとして扱われます)。


No