将多维数组传递给函数 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,如何将多维数组传递给 CLR/类库项目中的函数

c++ - 如何将多维数组传递给没有内部维度的函数? [复制]

C语言基础:C 中数组详解(多维数组传递数组给函数 从函数返回数组 指向数组的指针 )

如何将多维动态数组传递给C++中的函数

传递可变大小的多维数组

如何将零填充的多维数组传递给 C++ 中的函数?