给定以下代码:
void
foo( int* array )
{
// ...
}
void
bar( int** matrix )
{
// ...
}
int
main( void ) {
int array[ 10 ];
int matrix[ 10 ][ 10 ];
foo( array );
bar( matrix );
return 0;
}
我不明白为什么会收到此警告:
warning: passing argument 1 of ‘bar’ from incompatible pointer type
虽然 'foo' 调用似乎没问题。
谢谢:)
最佳答案
嗯,从 SO 的概览中可以看出,C 社区肯定没有很好地理解它。神奇的是,以下所有内容都是完全 100% 等效的:
void foo(int (*array)[10]);
void foo(int array[][10]);
void foo(int array[10][10]);
void foo(int array[42][10]);
区分指针和数组是非常重要的。 数组不是指针。数组可以转换为指向其第一个元素的指针。如果你有一个指针,你有这个:
--------
| ptr | -------> data
--------
但是,如果你有一个数组,你有这个:
---------------------------
| c1 | c2 | c3 | ... | cn |
---------------------------
有了指针,数据就在另一个星球上了,但是通过指针链接到了。数组本身就有数据。现在,多维数组只是数组的数组。数组嵌套到父数组中。所以,你的数组的大小是:
(sizeof(int) * 10) * 10
那是因为你有 10 个数组,所有数组都是 10 个整数的数组。现在,如果你想传递那个数组,它会被转换。但是为了什么?指向其第一个元素的指针。元素类型不是指针,而是数组。因此,您传递了一个指向 10 int 数组的指针:
int (*)[10] // a pointer to an int[10]
既不是int*
数组,也不是int**
数组。您可能会问为什么数组不作为 int**
传递。这是因为编译器必须知道行长。如果您执行 array[1][0]
,编译器将寻址距二维数组开头 sizeof(int) * 10
字节的位置。它以指向数组的指针类型解码该信息。
因此,您必须在上述完全等效的函数原型(prototype)中选择一个。当然,最后一个只是令人困惑。如果参数被声明为数组,编译器只会默默地忽略写入最外层维度的任何数字。所以我也不会使用倒数第二个版本。最好是使用第一个或第二个版本。重要的是要记住 C 没有(真正的)数组参数!该参数最后将是一个指针(在本例中为指向数组的指针)。
请注意上面的多维情况与下面的退化一维情况有何相似之处。以下 4 个版本都是完全等价的:
void foo(int *array);
void foo(int array[]);
void foo(int array[10]);
void foo(int array[42]);
关于c - 将数组和矩阵传递给函数作为 C 中的指针和指向指针的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/546860/