将多维数组传递给函数 C
Posted
技术标签:
【中文标题】将多维数组传递给函数 C【英文标题】:Passing multidimensional array to a function C 【发布时间】:2011-01-20 01:47:06 【问题描述】:我在将多维数组传递给 C 中的函数时遇到问题。无论是 typedef 还是参数应该是什么。
目前,我的函数 def 如下所示:
int foo(char *a, char b[][7], int first_dimension_of_array);
我这样声明一个数组:
char multi_D_array[20][7];
当我尝试这样调用函数时:
foo(d, multi_D_array, 20);
我收到警告,该函数的第二个参数来自不兼容的指针类型。我已经尝试了许多我在网上看到的变体,但仍然无法正确。此外,当使用 GDB 时,我发现只有二维数组的第一个数组被传入。如果我做错了什么,我们将不胜感激。
【问题讨论】:
尝试传递一个指向数组的指针 【参考方案1】:大警告:我通常不会以这种方式处理多维数组。
我试过这个只是为了检查,但是这个:
#include <stdio.h>
int foo(char b[][7])
printf("%d\n", b[3][4]);
return 0;
int main(int argc, char** argv)
char multi_d_arr[20][7];
multi_d_arr[3][4] = 42;
foo(multi_d_arr);
return 0;
使用gcc -Wall
编译和运行没有任何问题。老实说,我不确定第二个参数如何被视为不兼容的指针类型。工作正常。
但是,既然您问了,我将如何处理二维数组?更好的方法是使用这样的指针:
char** array2d = malloc((MAX_i+1)*sizeof(char*));
for ( i = 0; i < (MAX_i+1); i++ )
array2d[i] = malloc((MAX_j+1)*sizeof(char));
现在,为了清楚起见,您可以访问的最大元素是 array2d[MAX_i][MAX_j]
。
完成后不要忘记反转过程:
for ( i = 0; i < (MAX_i+1); i++ )
free(array2d[i]);
free(array2d);
现在,使用这种方法,下标符号仍然有效,所以array2d[x][y]
仍然可以访问正确的值。从字面上看,array2d
是一个指针数组,每个 array2d[i]
也是如此。
为什么这是一个更好的方法?好吧,如果您愿意,您可以拥有可变大小的子数组。您所要做的就是更改 for 循环。这种技术通常用于字符串数组,特别是在应用程序的int main(int argc, char** argv)
签名中。 argv
是一个可变长度字符串数组。使用strlen()
确定它们的长度。
你能把这个传过去吗?当然。对于初学者,您刚刚在 main 中收到它,但您也可以像这样编写函数签名:
int foo(char** ar2d, const unsigned int size);
然后调用它:
char** somearray;
/* initialisation of the above */
foo(ar2d, thesizeofar2d);
/* when done, free somearray appropriately */
需要明确的是,您包含尺寸参数的方法(如const unsigned int size
)是非常好的做法,您应该坚持下去。
【讨论】:
您可以使用 C99 可变长度数组做得更好,并根据其运行时大小声明数组的类型。你的建议真的是坏主意。如果子数组改变大小,您必须保持每一行的大小(或者如果它改变大小,则有访问外部未分配子数组的风险)。这意味着分配具有长度和指向数据的指针以及更复杂语法的结构。如果每个子数组的大小相同,那么使用一个 malloc 只分配一块内存会更高效、更易于阅读且不易出错。 澄清一下,我的意思是当子数组是字符串时,问题完全不同,因为零终止符隐含地给出子数组大小(字符串大小)并避免将其保持在结构中。此外,您经常希望存储指向静态分配的字符串的指针。这个用例是唯一的好用例,你不应该从中概括。【参考方案2】:您在问题中给出的声明和函数调用是完全正确的 C,并且没有使用 gcc 发出警告。
你确定你完全复制了有问题的代码吗?
【讨论】:
【参考方案3】:嗯,它在定义上是不兼容的。
char[20][7]
与char[][7]
不一样
只是摆脱警告。
并且它没有传递“仅传递二维数组的第一个数组”,它仅传递一个指向数组的指针(指向第一个元素的指针,或指向数组的开头)。 您只能看到 GDB 中的前 7 个元素,因为根据函数内部数组的类型,GDB 只知道 7 个元素。
【讨论】:
它们是兼容的。数组multi_D_array
,在函数调用上下文中使用时,被转换为指向其第一个元素的指针,其类型为char (*)[7]
。参数char [][7]
正是这种类型。【参考方案4】:
您的代码适合我吗?这是我的测试代码:http://codepad.org/wSppLiwl
【讨论】:
【参考方案5】:从 C99 开始,您可以拥有可变长度数组并执行以下操作。基本上为维度数组提供的参数用于声明数组大小。这很可能是现代编译器的最佳方法。
#include <stdio.h>
int foo(char *a, int fdim, char b[fdim][7])
printf("b[19][6] = %d\n", b[19][6]);
return 0;
int main()
char d[10];
char multi_D_array[20][7];
int x, y;
for (x = 0 ; x < 7 ; ++x)
for (y=0 ; y < 20 ; ++y)
multi_D_array[y][x] = y + x;
foo(d, 20, multi_D_array);
即使它也适用于 C++,您也可以通过阅读我的回答 there 和 there(当然还有其他人的回答)来更好地理解 C 数组。
【讨论】:
正确,只是对于第一个维度,这并没有改变。您的声明完全等同于 OP 给出的声明(但转换位置)。只有从第二维 VLA 开始,作为函数参数才会带来新的东西。【参考方案6】:底线是 C/C++ 不能很好地处理多维数组。大多数情况下,将其设置为一维数组并自己进行行列寻址会更容易。
【讨论】:
以上是关于将多维数组传递给函数 C的主要内容,如果未能解决你的问题,请参考以下文章
c++ - 如何将多维数组传递给没有内部维度的函数? [复制]