在一个函数中操作multidimensional array

我在这里读了很多东西,并尝试了很多,但我找不到一个方法来传递一个multidimensional array到一个函数在C中,改变一些值,并以某种方式返回新的数组。 find一种方法将数组传递给另一个函数并执行相同的操作是非常重要的。

我想find一种方法将数组传递给一个函数。然后将它从第一个函数传递到第二个函数,在那里做一些事情(也许是打印,也许更改值),然后再次使用它到第一个函数,最后使用在主数组中。

我最后的尝试是:

void func(int multarray[][columns]){ multarray[0][0]=9; } int main(){ int rows; int columns; int multarray[rows][columns]; func(multarray); return 0; } 

我也试过这个:

 void func(int multarray[rows][columns]){ multarray[0][0]=9; } int main(){ int rows; int columns; int multarray[rows][columns]; func(multarray); return 0; } 

我也试过这个:

 int getid(int row, int x, int y) { return (row*x+y); } void printMatrix(int*arr, int row, int col) { for(int x = 0; x < row ; x++) { printf("\n"); for (int y = 0; y <col ; y++) { printf("%d ",arr[getid(row, x,y)]); } } } main() { int arr[2][2] = {11,12,21,22}; int row = 2, col = 2; printMatrix((int*)arr, row, col); } 

从这里

我也尝试了双指针。我还读到,如果编译器不支持VLA,还有一种不同的方法。 我正在使用gnu。

不完全确定,问题是什么,但这个工作(并打印值“9”):

 #include <stdio.h> #define ROWS 10 #define COLUMNS 10 void func2(int multarray[][COLUMNS]){ multarray[1][4]=10; } void func1(int multarray[][COLUMNS]){ multarray[0][3]=9; func2(multarray); } int main(){ int multarray[ROWS][COLUMNS]; func1(multarray); printf("%d\n", multarray[0][3]); printf("%d\n", multarray[1][4]); return 0; } 

请注意,传递给函数时,数组会衰减到指针。

有几件事要记住:

  1. 当你将一个数组expression式作为parameter passing给一个函数时,它将从一个types为“ T N元素数组”的expression式转换为“指向T指针”,expression式的值将是第一个数组的元素。 被调用的函数接收一个指针值。

  2. []运算符可以用于数组或指针types的expression式; IOW,声明在int a[10]; int *p = a; int a[10]; int *p = a; ,那么p[i]a[i]指向相同的元素。

  3. 当声明接受VLA作为参数的函数时,必须声明数组之前声明指定维的参数。

所以,对于一个操作二维VLA的函数,你会写一些类似的东西

 void foo( size_t rows, size_t cols, int (*multiarray)[cols] ) // or multiarray[][cols] { size_t i, j; for ( i = 0; i < rows; i++ ) for ( j = 0; j < cols; j++ ) multiarray[i][j] = some_value(); } 

怎么了int (*multiarray)[cols] ? 请记住,在将数组expression式作为parameter passing时,数组expression式的types将从“ T N元素数组”转换为“指向T指针”。 在这种情况下, T是“ cols intle数组”,所以我们从“ rows -element数组中的元素”到“指向cols元素的数组”。 在函数参数声明的上下文中, T a[N]T a[]T *a都是相同的。 在这三种情况下, a被声明为T指针 。 所以int (*multiarray)[cols]相当于int multiarray[][cols] ,这相当于int multiarray[rows][cols] 。 我更喜欢使用第一种forms,因为它最准确地代表了情况。

如果你想把这个数组作为parameter passing给另一个函数,你可以使用相同的types:

 void bar( size_t rows, size_t cols, int (*multiarray)[cols] ) { foo( rows, cols, multiarray ); } int main( void ) { size_t rows = 0; size_t cols = 0; // you must assign values to rows and cols before declaring a VLA with them rows = ...; cols = ...; int arr[rows][cols]; bar( rows, cols, arr ); ... } 

foo对数组内容进行的任何更改都会反映在barmain

VLA可能是有用的,但他们有其局限性。 它们不能被声明为static ,也不能被定义在函数之外。 他们不能使用{}风格的初始化语法。 而且,VLA支持现在是2011年标准的可选项,所以您不能依赖于它们在任何地方的支持。

如果没有可用的VLA,并且在运行时未知数组大小,则必须使用dynamic内存分配( malloccalloc ),并且传递给函数的types将会不同:

 void foo( size_t rows, size_t cols, int **multiarray ) { size_t i, j; for ( i = 0; i < rows; i++ ) for ( j = 0; j < cols; j++ ) multiarray[i][j] = some_value(); } void bar( size_t rows, size_t cols, int **multiarray ) { foo( rows, cols, multiarray ); } int main( void ) { size_t rows; size_t cols; int **multiarray = NULL; ... // get rows and cols // allocate memory for pointers to each row multiarray = malloc( sizeof *multiarray * rows ); if ( multiarray ) { size_t i; // allocate each row for ( i = 0; i < rows; i++ ) { multiarray[i] = malloc( sizeof *multiarray[i] * cols ); if ( !multiarray[i] ) break; } if ( i < rows ) { // malloc failed for one of the multiarray rows; we need to // free whatever memory has already been allocated and exit while ( i-- ) free( multiarray[i] ); free( multiarray ); exit(0); } } bar ( rows, cols, multiarray ); ... if ( multiarray ) { size_t i; for ( i = 0; i < rows; i++ ) free( multiarray[i] ); free( multiarray ); } } 

这种方法的一个缺点是分配的内存不能保证是连续的(即,行不会在内存中相邻)。 如果那么重要,你将不得不采取另一种方法。 不是分别分配行和列,而是将所有内容分配到一个块中,然后手动映射数组索引:

 void foo( size_t rows, size_t cols, int *fakemultiarray ) { size_t i, j; for ( i = 0; i < rows; i++ ) for ( j = 0; j < rows; j++ ) fakemultiarray[ i * rows + j ] = some_value(); } void bar( size_t rows, size_t cols, int *fakemultiarray ) { foo( rows, cols, fakemultiarray ); } int main( void ) { size_t rows; size_t cols; int *fakemultiarray = NULL; ... // get rows and cols fakemultiarray = malloc( sizeof *fakemultiarray * rows * cols ); if ( fakemultiarray ) bar( rows, cols, fakemultiarray ); ... free( fakemultiarray ); } 

在这种情况下,我们已经为所有元素分配了足够大的单个缓冲区,但是我们必须将其索引为一维数组,将索引计算为i * rows + j

对于你的二维数组,我会为它定义一个types。

 typedef int my2DArray_t[ROWS][COLUMNS]; 

然后你可以声明这个types的variables和指向它们的指针。 这使得更容易传递信息。

 void someFuncOther (my2DArray_t *someArray) { /* Set some values in array */ (*someArray)[1][1] = 4; } void someFunc (my2DArray_t *someArray) { /* Set some values in array */ (*someArray)[1][0] = 7; /* Have someFuncOther do some more work */ someFuncOther (someArray); } int main (void) { /* This is the actual array */ my2DArray_t myArray; /* Set some values in array */ myArray[0][2] = 6; /* Have someFunc do some work on myArray by passing a pointer to it */ someFunc (&myArray); } 

将数组视为指向内存的指针是有帮助的。 然后很容易想到一个2d数组作为指针的内存指针(有点儿)

这是不行的

  int arr[2][2] = {11,12,21,22}; //not going to work 

但是这对我来说工作得很好

  1 #include <stdio.h> 2 3 4 main() 5 { 6 int arr[2][2] = {{11,1},{2,21}}; 7 int row = 2, col = 2; 8 int i,j; 9 10 for(i=0;i<row;i++) 11 for(j=0;j<col;j++) 12 printf("%d - ",arr[i][j]); 13 14 15 }