【问题标题】:Passing multidimensional array in c90 (pre VLA-style)在 c90 中传递多维数组(pre VLA-style)
【发布时间】:2015-08-17 17:33:03
【问题描述】:

鉴于自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;
                }
        }
}

但据我了解,这仅适用于 VLA,我可以在函数参数列表中简单地指定 (*ptr_arr)[n]?在c90 中是否有其他方法可以做到这一点,特别注意foo_c()

1. 请不要对系统进行抨击。

【问题讨论】:

  • 你可以void foo_a_10_20(int array[10][20])
  • 是的,但是这个想法,也许我没有足够强调这一点,是我事先不知道数组的大小。
  • 我认为你做不到。
  • 您需要自己正确地进行指针运算。 *(arr + i*n + j)恐怕...
  • @Eregrith,指向 int 的指针与多维数组不同。索引使用不同的算法。

标签: c arrays multidimensional-array


【解决方案1】:

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

例子:

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

【讨论】:

  • 在第二个涉及malloc()ed 数组的示例中,您回答了一个我已经在脑后排好队的问题。非常好!
猜你喜欢
  • 1970-01-01
  • 2016-04-06
  • 2010-09-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多