2011-01-20 85 views
3

我在将多维数组传递给C中的函数时遇到了问题。在typedef中以及参数应该是什么。将多维数组传递给函数C

目前,我的功能高清看起来是这样的:

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时,我发现只有2D数组的第一个数组被传入。对于我所做错误的反馈将不胜感激。

+1

尝试将指针传递给数组 – 2011-01-20 01:48:48

回答

5

大警告:我通常不会这样处理多维数组。

我想这只是为了检查,但这:

#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()来确定它们的长度。

你能通过吗?当然。你刚刚收到它的主,对于初学者,但你也可以写你的函数签名如下所示:

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)是非常好的做法,你应该坚持下去。

+0

对于你在答案中所做的工作+1 :) – 2011-01-20 02:31:09

+0

使用C99变长数组可以做得更好,并根据它的运行时大小声明数组的类型。你的建议是真的**不好主意**。如果子数组更改大小,则必须*保留每行的大小(或者如果大小更改,则风险访问外部未分配的子数组)。这意味着要分配一个结构长度和指针数据和更复杂的语法。如果每个子数组的大小相同,那么只用一个malloc分配一块内存会更高效,更易于阅读并且不易出错。 – kriss 2011-01-20 07:47:03

-2

底线是C/C++不能很好地处理多维数组。大多数情况下,使它成为一个单维数组并自己进行行列寻址更容易。

0

那么,它是不符合定义的。

char[20][7]是不一样的char[][7]

刚刚摆脱的警告。

它不传递“只有2D数组的第一个数组”,它只传递一个指向数组的指针(指向第一个元素的指针或数组的开头)。 您只能看到GDB中的前7个元素,因为根据函数内部数组的类型,GDB只知道7个元素。

+1

它们是兼容的。数组`multi_D_array`在函数调用上下文中使用时,被转换为指向其第一个元素的指针,该元素的类型为char(*)[7]`。参数`char [] [7]`正是这种类型。 – caf 2011-01-20 03:22:49

0

从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++,你也可能有意通过阅读我的答案therethere(别人的肯定回答)为更好地理解C数组中。

1

你在问题中给出的声明和函数调用是完全正确的C,并且不会给gcc一个警告。

你确定你已经完全复制了有问题的代码吗?