Pass By Reference Multidimensional Array With Unknown Size

前端 未结 5 540
没有蜡笔的小新
没有蜡笔的小新 2021-01-21 10:36

How to pass by reference multidimensional array with unknown size in C or C++?

EDIT:

For example, in main function I have:

int main(){
    int          


        
相关标签:
5条回答
  • 2021-01-21 10:54

    H2CO3's solution will work for C99 or a C2011 compiler that supports VLAs. 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.

    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:

    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.

    0 讨论(0)
  • 2021-01-21 10:54

    This is a sort of comment to the good answer of @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];

      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.

    0 讨论(0)
  • 2021-01-21 10:58

    Simply put, you can't. In C, you can't pass by reference, since C has no references. In C++, you can't pass arrays with unknown size, since C++ doesn't support variable-lenght arrays.

    Alternative solutions: in C99, pass a pointer to the variable-length array; in C++, pass a reference to std::vector<std::vector<T>>.

    Demonstration for 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:

    #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;
    }
    
    0 讨论(0)
  • 2021-01-21 10:58

    John Bode's explanation is very good, but there is a little mistake: it should be

    i * cols + j
    

    instead of

    i * rows + j
    
    0 讨论(0)
  • 2021-01-21 11:02

    If you really want references, then it's only in C++.

    En example of a two-dimensional int array passed by reference

    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.

    0 讨论(0)
提交回复
热议问题