通过参考传递具有未知大小的多维数组

如何在C或C ++中通过引用未知大小的多维数组?

编辑:

例如,在main函数中我有:

int main(){ int x, y; int arr[x][y]; // pass_by_ref(/* passing just arr[][] by reference */); } 

和function:

 void pass_by_ref(/* proper parameter for arr[][] */){ // int size_x_Arr = ??? // int size_y_arr = ??? } 

如何实现评论行?

简单地说,你不能。 在C中,您不能通过引用传递,因为C没有引用。 在C ++中,您无法传递大小未知的数组,因为C ++不支持变量长度数组。

替代解决方案:在C99中,将指针传递给可变长度数组; 在C ++中,传递对std::vector>的引用。

C99演示:

 #include  void foo(int n, int k, int (*arr)[n][k]) { int i, j; for (i = 0; i < n; i++) { for (j = 0; j < k; j++) { printf("%3d ", (*arr)[i][j]); } printf("\n"); } } int main(int argc, char *argv[]) { int a = strtol(argv[1], NULL, 10); int b = strtol(argv[2], NULL, 10); int arr[a][b]; int i, j; for (i = 0; i < a; i++) { for (j = 0; j < b; j++) { arr[i][j] = i * j; } } foo(a, b, &arr); return 0; } 

C ++ 03的演示:

 #include  #include  #include  #include  void foo(std::vector < std::vector < int > > &vec) { for (std::vector < std::vector < int > >::iterator i = vec.begin(); i != vec.end(); i++) { for (std::vector::iterator j = i->begin(); j != i->end(); j++) { std::cout << *j << " "; } std::cout << std::endl; } } int main(int argc, char *argv[]) { int i = strtol(argv[1], NULL, 10); int j = strtol(argv[2], NULL, 10); srand(time(NULL)); std::vector < std::vector < int > > vec; vec.resize(i); for (std::vector < std::vector < int > >::iterator it = vec.begin(); it != vec.end(); it++) { it->resize(j); for (std::vector::iterator jt = it->begin(); jt != it->end(); jt++) { *jt = random() % 10; } } foo(vec); return 0; } 

H2CO3的解决方案适用于支持VLA的C99或C2011编译器。 对于支持VLA的C89或C2011编译器,或者(上帝禁止)K&R C编译器,您必须做其他事情。

假设您正在传递一个连续分配的数组,您可以将指针传递给第一个元素&a[0][0] )以及尺寸大小,然后将其视为一维数组,映射索引如下:

 void foo( int *a, size_t rows, size_t cols ) { size_t i, j; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { a[i * rows + j] = some_value(); } } } int main( void ) { int arr[10][20]; foo( &arr[0][0], 10, 20 ); ... return 0; } 

这适用于堆栈上分配的数组:

 T a[M][N]; 

对于动态分配的表单数组:

 T (*ap)[N] = malloc( M * sizeof *ap ); 

因为两者都会连续分配行。 对于动态分配的表单数组,这不起作用(或者至少不能保证工作):

 T **ap = malloc( M * sizeof *ap ); if (ap) { size_t i; for (i = 0; i < M; i++) { ap[i] = malloc( N * sizeof *ap[i] ); } } 

因为不能保证所有行都会相互连续分配。

这是对@John Bode的好答案的一种评论

对于动态分配的表单数组,这不起作用(或者至少不能保证工作):

但这个变种将:

 T **ap = malloc( M * sizeof *ap ); if (ap) return NULL; ---> some error atention if (ap) { ap[0] = malloc( M * N * sizeof *ap[i] ); if (ap[0]) { free(ap); return NULL;} ---> some error atention size_t i; for (i = 1; i < M; i++) { ap[i] = ap[0] + i * N; } } 

使用后:

 free(ap[0]); free(ap); 

对于Tint你调用foo正好为数组int ap[M][N];

  foo( &ap[0][0], M, N); 

因为您保证所有行都是相互连续分配的。 这种分配更有效率。

约翰博德的解释非常好,但有一点错误:它应该是

 i * cols + j 

代替

 i * rows + j 

如果你真的想要引用,那么它只在C ++中。

En通过引用传递的二维int数组的示例

 void function_taking_an_array(int**& multi_dim_array); 

但是参考没有任何优势,所以只需使用:

 void function_taking_an_array(int** multi_dim_array); 

我建议你使用容器来保存你的arrays。