在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操作符中,当应用于作为参数传递的数组时,它也总是将其视为指向第一个元素的指针)。
data
?我尝试使用int* data
,但不起作用。 - glc78int data[height][width];
或者使用int (*data)[width] = malloc(height*sizeof(*data));
在堆上进行存储。在这两种情况下,您都可以按照正常方式访问data[y][x]
并将其传递给f(width, data)
。 - cmaster - reinstate monica你可以对任何数据类型进行这样的操作。只需将其指针改为指向指针:
typedef struct {
int myint;
char* mystring;
} data;
data** array;
但不要忘记您仍需为变量分配内存,这会变得有些复杂:
//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.
[][]
语法,它并不能神奇地变成一个数组。你不能对其进行 memcpy() 等操作,因为内存不是在相邻的内存单元中分配的,这是数组所必需的。你的查找表会分散在堆上,使得查找变慢并且堆碎片化。 - Lundinvoid 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 );
同样地,例如一个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
具有可用于指示最终、最低级别的单维X
数组结束的哨兵值。
例如,传递给main()
的char **argv
值是指向char
指针数组的指针。初始的char *
指针数组以NULL
哨兵值结束,而由char *
指针数组引用的每个char
数组以'\0'
字符值结束。
例如,如果您可以使用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
}
p[i*Y+j*Z+k]
应该改为p[i*Y*Z+j*Z+k]
。 - David Hp[i*N+j]
来访问多维数组中的特定元素? - F. Zer