繁体   English   中英

在 C 中将多维数组作为函数参数传递

[英]Passing multidimensional arrays as function arguments in C

C中,当我不知道数组的维数是多少时,我可以将多维数组作为单个参数传递给函数吗?

此外,我的多维数组可能包含字符串以外的类型。

将显式指针传递到第一个元素,并将数组维度作为单独的参数。 例如,要处理任意大小的二维 int 数组:

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);

您可以将函数声明为:

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

然后编译器会为你做所有的指针运算。

请注意,维度大小必须出现数组本身之前

GNU C 允许参数声明转发(以防您确实需要在数组之后传递维度):

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

第一个维度,虽然你也可以作为参数传递,但对于 C 编译器来说是无用的(即使对于 sizeof 运算符,当应用于作为参数传递的数组时,总是将 is 视为指向第一个元素的指针)。

您可以使用任何数据类型执行此操作。 简单地使它成为一个指针到指针:

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");
  }
}

解除分配结构的代码看起来很相似——不要忘记对你分配的所有东西调用 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.

在 C 中,当我不知道数组的维数是多少时,我可以将多维数组作为单个参数传递给函数吗?

如果“单个参数”是指仅传递数组而不传递数组维度,则不可以。 至少不是真正的多维数组。

您可以将维度 [s] 与数组一起放入一个结构中,并声称您正在传递“单个参数”,但这实际上只是将多个值打包到一个容器中并将该容器称为“一个参数”。

您可以通过传递维度本身和数组来传递已知类型和维度数量但未知大小的数组,如下所示:

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 );

类似地,一个 3 维数组,例如一个struct pixel

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

或一维double数组:

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

但...

然而,它可以是能够通过“指针数组的指针为...类型的数组的数组X ”,常常错误标记为“多维数组”构建体作为单个参数,只要该碱型X具有可用于指示最终的最低级别的X类型一维数组的结束的哨兵值。

例如,传递给main()char **argv值是一个指向char指针数组的指针。 char *指针的初始数组以NULL标记值结束,而char *指针数组引用的每个char数组以'\\0'NUL字符值结束。

例如,如果您可以使用NAN作为标记值,​​因为实际数据永远不会是NAN ,您可以像这样打印double **

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++;
    }
}
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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM