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

Dav*_*vid 51 c

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

另外,我的多维数组可能包含除字符串以外的类型.

Joh*_*ode 31

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

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

这将被称为

...
int arr1[10][20];
int arr2[5][80];
...
func_2d(&arr1[0][0], 10, 20);
func_2d(&arr2[0][0], 5, 80);
Run Code Online (Sandbox Code Playgroud)

同样的原则适用于高维数组:

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);
Run Code Online (Sandbox Code Playgroud)

  • `p [i*Y + j*Z + k]`应该是'p [i*Y*Z + j*Z + k]`. (2认同)

and*_*wrk 21

您可以使用任何数据类型执行此操作.只需将其指向指针即可:

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

data** array;
Run Code Online (Sandbox Code Playgroud)

但是不要忘记你仍然需要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");
  }
}
Run Code Online (Sandbox Code Playgroud)

解除分配结构的代码看起来很相似 - 不要忘记在malloced的所有内容上调用free()!(另外,在健壮的应用程序中,你应该检查malloc()的返回.)

现在让我们假设你要将它传递给一个函数.您仍然可以使用双指针,因为您可能希望对数据结构进行操作,而不是对数据结构指针的指针:

int whatsMyInt(data** arrayPtr, int x, int y){
  return arrayPtr[y][x].myint;
}
Run Code Online (Sandbox Code Playgroud)

调用此函数:

printf("My int is %d.\n", whatsMyInt(array, 2, 4));
Run Code Online (Sandbox Code Playgroud)

输出:

My int is 6.
Run Code Online (Sandbox Code Playgroud)

  • 指向分段查找表的指针不是2D数组.仅仅因为它允许`[] []`语法,它不会神奇地变成一个数组.你不能memcpy()它等因为内存没有分配在相邻的存储单元中,这是数组所必需的.您的查找表分散在整个堆中,使查找速度变慢,堆碎片化. (4认同)

rsl*_*mos 18

您可以将您的函数声明为:

f(int size, int data[][size]) {...}
Run Code Online (Sandbox Code Playgroud)

然后编译器将为您执行所有指针运算.

请注意,尺寸大小必须出现数组本身之前.

GNU C允许参数声明转发(如果你真的需要在数组后传递维度):

f(int size; int data[][size], int size) {...}
Run Code Online (Sandbox Code Playgroud)

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

  • IMO 这应该是公认的答案。不需要额外的代码,也不需要不必要的堆分配。简单干净 (2认同)