在c90中传递多维数组(前VLA风格)

时间:2015-06-03 13:16:41

标签: c arrays multidimensional-array

鉴于自c99以来VLA的增加,将未知大小的多维数组传递给函数变得更容易。但是关于使用VLA存在相当多的争议。有些人很容易认可"It is often nicer to use dynamic memory, alloca() or VLAs." 1 其他scorne them。我问自己的问题是将多维数组传递给函数的c90天的标准方法。这是一个小代码:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{

        int arr[2][4];

        int i;
        int j;

        for(i = 0; i < 2; i++) {
                for(j = 0; j < 4; j++) {
                        arr[i][j] = j;
                }
        }    
        exit(EXIT_SUCCESS);
}

我可以想到一种方法:将指针传递给指针:

void foo_a(int m, int n, int **ptr_arr)
{
        int i, j;
        for (i = 0; i < m; i++) {
                for (j = 0; j < n; j++) {
                        ptr_arr[i][j] += 1;
                }
                printf("\n");
        }
}

但是,这将涉及通过插入类似于main(这不是很漂亮)的东西来展平数组。

int *unidim_arr[ROW];
for (i = 0; i < ROW; i++) {
        unidim_arr[i] = &(arr[i][0]);
}

另一个人可能会使用单个指针并手动计算偏移量,这很容易出错:

void foo_b(int m, int n, int *ptr_arr)
{
        int i, j;
        for (i = 0; i < m; i++) {
                for (j = 0; j < n; j++) {
                         *((ptr_arr + i * n) + j) += 1;
                }
        }
}

让我觉得最好的解决方案是使用像

这样的东西
void foo_c(int m, int n, int (*ptr_arr)[])
{
        int i, j;
        for (i = 0; i < m; i++) {
                for (j = 0; j < n; j++) {
                        ptr_arr[i][j] += 1;
                }
        }
}

但根据我的理解,这只适用于我可以在函数参数列表中指定(*ptr_arr)[n]的VLA?是否有另一种方法可以在c90中进行,并特别关注foo_c()

<子> 请不要系统抨击。

1 个答案:

答案 0 :(得分:2)

一种方法是将指针传递给数组的第一个元素以及数组维度,然后将该指针视为函数中的一维数组。

示例:

void foo( int *arr, size_t r, size_t c )  // process a 2D array defined as int arr[r][c]
{
  for ( size_t i = 0; i < r; i++ )
    for ( size_t j = 0; j < c; j++ )
      arr[i * r + j] = some_value();  // calculate index manually
}

int main( void )
{
  int arr[4][5];

  foo( &arr[0][0], 4, 5 );
}

这很容易扩展到更高尺寸的数组。当然,这仅适用于真正的多维数组,其中行在内存中都是相邻的。这对于一次动态分配一行的数组不起作用,例如

int **arr = malloc( sizeof *arr * rows );
for ( size_t i = 0; i < rows; i++ )
  arr[i] = malloc( sizeof *arr[i] * cols );

因为行不能保证相邻,但在这种情况下,您只需按原样使用arr指针:

void bar( int **arr, size_t r, size_t c ) // process a 2D array defined as int **arr
{
  for ( size_t i = 0; i < r; i++ )
    for ( size_t j = 0; j < c; j++ )
      arr[i][j] = some_value();
}