鉴于自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()
?
<子> 请不要系统抨击。 子>
答案 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();
}