[英]Pass By Reference Multidimensional Array With Unknown Size
如何在C或C ++中通过未知大小的引用多维数组传递?
例如,在主要功能中,我有:
int main(){
int x, y;
int arr[x][y];
// pass_by_ref(/* passing just arr[][] by reference */);
}
和功能:
void pass_by_ref(/* proper parameter for arr[][] */){
// int size_x_Arr = ???
// int size_y_arr = ???
}
如何实施注释行?
简而言之,你不能。 在C中,您无法通过引用传递,因为C没有引用。 在C ++中,您无法传递大小未知的数组,因为C ++不支持可变长度数组。
替代解决方案:在C99中,将指针传递给可变长度数组; 在C ++中,传递对std::vector<std::vector<T>>
的引用。
C99的演示:
#include <stdio.h>
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 <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
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<int>::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<int>::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]
维度大小传递给第一个元素 ( &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);
对于T
为int
您可以为int ap[M][N];
数组恰好调用foo
int ap[M][N];
foo( &ap[0][0], M, N);
因为您保证所有行都是连续分配的。 这种分配效率更高。
John Bode的解释很好,但有一个小错误:应该是
i * cols + j
代替
i * rows + j
如果您真的想要引用,则仅在C ++中。
通过引用传递的二维int数组的示例
void function_taking_an_array(int**& multi_dim_array);
但是引用没有任何优势,因此只需使用:
void function_taking_an_array(int** multi_dim_array);
我建议您使用容器保存阵列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.