55

配列の次元が不明な場合、多次元配列を単一の引数として関数Cに渡すことはできますか?

また、多次元配列には文字列以外の型が含まれている場合があります。

4

5 に答える 5

36

配列の次元を個別のパラメーターとして使用して、最初の要素への明示的なポインターを渡します。たとえば、任意のサイズの 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);
于 2009-12-16T17:18:33.383 に答える
23

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

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.
于 2008-08-07T00:34:21.097 に答える
1

C では、配列の次元が不明な場合に、多次元配列を単一の引数として関数に渡すことはできますか?

いいえ

「単一の引数」によって、配列の次元を渡さずに配列だけを渡すことを意味する場合は、できません。少なくとも真の多次元配列ではありません。

次元を配列とともに構造体に入れ、「単一の引数」を渡していると主張できますが、それは実際には複数の値を単一のコンテナーにパックし、そのコンテナーを「1 つの引数」と呼んでいるだけです。

次のように、次元自体と配列を渡すことで、既知の型と次元数の配列を渡すことができますが、サイズは不明です。

void print2dIntArray( size_t x, size_t y, int array[ x ][ y ] )
{
    for ( size_t ii = 0, ii < x; ii++ )
    {
        char *sep = "";
        for ( size_t jj = 0; jj < y; jj++ )
        {
            printf( "%s%d", sep, array[ ii ][ jj ] );
            sep = ", ";
        }
        printf( "\n" );
    }
}

その関数を次のように呼び出します。

int a[ 4 ][ 5 ];
int b[ 255 ][ 16 ];

...

print2dIntArray( 4, 5, a );

....

printt2dIntArray( 255, 16, b );

同様に、たとえば a の 3 次元配列struct pixel:

void print3dPixelArray( size_t x, size_t y, size_t z, struct pixel pixelArray[ x ][ y ][ z ] )
{
    ...
}

または 1 次元double配列:

void print1dDoubleArray( size_t x, double doubleArray[ x ] )
{
    ...
}

しかし...

ただし、基本型にセンチネル値があるX限り、「多次元配列」として誤ってラベル付けされることが多い「型の配列のポインターの配列へのポインターの配列」を渡すことは可能です。Xtype の最終的な最下位レベルの 1 次元配列の終わりを示すために使用できますX

たとえば、 にchar **argv渡される値main()は、 へのポインターの配列へのポインターcharです。char *ポインターの初期配列はNULLセンチネル値で終わりますが、ポインターcharの配列によって参照される各配列はの文字値でchar *終わります。NUL'\0'

たとえば、NAN実際のデータNANdouble **.

void printDoubles( double **notAnArray )
{
    while ( *notAnArray )
    {
        char *sep = "";
        for ( size_t ii = 0;  ( *notAnArray )[ ii ] != NAN; ii++ )
        {
            printf( "%s%f", sep, ( *notAnArray )[ ii ] );
            sep = ", ";
        }

        notAnArray++;
    }
}
于 2019-12-13T11:22:39.827 に答える
-2
int matmax(int **p, int dim) // p- matrix , dim- dimension of the matrix 
{
    return p[0][0];  
}

int main()
{
   int *u[5]; // will be a 5x5 matrix

   for(int i = 0; i < 5; i++)
       u[i] = new int[5];

   u[0][0] = 1; // initialize u[0][0] - not mandatory

   // put data in u[][]

   printf("%d", matmax(u, 0)); //call to function
   getche(); // just to see the result
}
于 2012-01-03T12:51:47.267 に答える