通过引用传递未知大小的多维数组

Pass By Reference Multidimensional Array With Unknown Size

本文关键字:数组 未知 引用      更新时间:2023-10-16

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

编辑:

例如,在main函数中:

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的解决方案将适用于C99或支持vla的C2011编译器。对于不支持vla的C89或C2011编译器,或者(上帝禁止)K& C编译器,您必须做其他事情。

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

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);

,因为您保证所有的行都是连续地分配给彼此的。

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);
我建议你使用容器来保存你的数组。