简体   繁体   English

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

[英]Pass By Reference Multidimensional Array With Unknown Size

How to pass by reference multidimensional array with unknown size in C or C++? 如何在C或C ++中通过未知大小的引用多维数组传递?

EDIT: 编辑:

For example, in main function I have: 例如,在主要功能中,我有:

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

and the function: 和功能:

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

How to implement the commented line? 如何实施注释行?

Simply put, you can't. 简而言之,你不能。 In C, you can't pass by reference, since C has no references. 在C中,您无法通过引用传递,因为C没有引用。 In C++, you can't pass arrays with unknown size, since C++ doesn't support variable-lenght arrays. 在C ++中,您无法传递大小未知的数组,因为C ++不支持可变长度数组。

Alternative solutions: in C99, pass a pointer to the variable-length array; 替代解决方案:在C99中,将指针传递给可变长度数组; in C++, pass a reference to std::vector<std::vector<T>> . 在C ++中,传递对std::vector<std::vector<T>>的引用。

Demonstration for C99: 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;
}

Demonstration for C++03: 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's solution will work for C99 or a C2011 compiler that supports VLAs. H2CO3的解决方案适用于支持VLA的C99或C2011编译器。 For C89 or a C2011 compiler that doesn't support VLAs, or (God forbid) a K&R C compiler, you'd have to do something else. 对于支持VLA的C89或C2011编译器,或(上帝禁止)K&R C编译器,您必须执行其他操作。

Assuming you're passing a contiguously allocated array, you can pass a pointer to the first element ( &a[0][0] ) along with the dimension sizes, and then treat it as a 1-D array, mapping indices like so: 假设您要传递连续分配的数组,则可以将指针&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;
}

This will work for arrays allocated on the stack: 这将适用于在堆栈上分配的数组:

T a[M][N];

and for dynamically allocated arrays of the form: 对于以下形式的动态分配数组:

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

since both will have contiguously allocated rows. 因为两者都会连续分配行。 This will not work (or at least, not be guaranteed to work) for dynamically allocated arrays of the form: 不会对形式的动态分配数组工作(或至少,不能保证工作):

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

since it's not guaranteed that all the rows will be allocated contiguously to each other. 因为不能保证所有行都可以连续分配。

This is a sort of comment to the good answer of @John Bode 这是对@John Bode的良好答案的一种评论

This will not work (or at least, not be guaranteed to work) for dynamically allocated arrays of the form: 对于以下形式的动态分配的数组,这将不起作用(或至少不能保证起作用):

But this variant will: 但是此变体将:

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

After use : 使用后:

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

for T being int you call foo exactly als for the array int ap[M][N]; 对于Tint您可以为int ap[M][N];数组恰好调用foo int ap[M][N];

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

since you guaranteed that all the rows are allocated contiguously to each other. 因为您保证所有行都是连续分配的。 This allocation is a litter more efficient. 这种分配效率更高。

John Bode's explanation is very good, but there is a little mistake: it should be John Bode的解释很好,但有一个小错误:应该是

i * cols + j

instead of 代替

i * rows + j

If you really want references, then it's only in C++. 如果您真的想要引用,则仅在C ++中。

En example of a two-dimensional int array passed by reference 通过引用传递的二维int数组的示例

void function_taking_an_array(int**& multi_dim_array);

But the reference doesn't have any advantage, so simply use : 但是引用没有任何优势,因此只需使用:

void function_taking_an_array(int** multi_dim_array);

I would advice you to use a container to hold your array. 我建议您使用容器保存阵列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM