将数组和矩阵传递给函数作为指针和指向C中的指针

给出以下代码:

void foo( int* array ) { // ... } void bar( int** matrix ) { // ... } int main( void ) { int array[ 10 ]; int matrix[ 10 ][ 10 ]; foo( array ); bar( matrix ); return 0; } 

我不明白为什么我会收到这个警告:

警告:从不兼容的指针类型传递’bar’的参数1

虽然’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是:

 (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个字节,距离2维数组的开头。 它在指针到数组类型中解码该信息。

因此,您必须选择上述完全等效的函数原型之一。 当然,最后一个只是令人困惑。 如果将参数声明为数组,编译器会默默地忽略在最外层维度中编写的任何数字。 所以我也不会使用倒数第二个版本。 最好是使用第一个或第二个版本。 重要的是要记住C没有(真正的)数组参数 ! 该参数将是末尾的指针(在这种情况下指向数组的指针)。

注意上面的多维情况如何类似于下面的简并一维情况。 以下所有4个版本完全等效:

 void foo(int *array); void foo(int array[]); void foo(int array[10]); void foo(int array[42]); 

在C中传递多维数组是一个棘手的主题。 请参阅此常见问题

要问的问题是你将如何使用bar 。 如果你总是知道它将被传递一个10×10数组然后重写为

 bar(int matrix[10][10]); 

如果你想处理不同维度的数组,那么你可能需要传入长度:

 bar(int *matrix, int width, int height); 

问题是数据结构矩阵[10] [10]实际上不是指向数组[10]的十个指针的表,但它是一个100个整数的顺序数组。 酒吧的正确签名是

 bar (int matrix[10][10]) 

如果你真的想使用间接表示矩阵并且使用int **矩阵作为bar的参数类型,那么你需要以不同的方式分配它:

 int *matrix[10]; int my_data[100]; int i; for (i = 0; i < 10; i++) { matrix[i] = &(my_data[i * 10]); } bar(matrix); 

现在'矩阵'匹配int **类型。 'matrix'是一个由十个指针组成的数组,你可以通过指针传递它,因此得到第二个*。

下面是一些要练习的代码 – 它包含了传递2维数组和访问元素值的代码的所有可能类型

 #include  #define NUMROWS 2 #define NUMCOLUMNS 5 #define FILL_ARRAY() \ *array[0] = '1'; \ (*array)[7] = '2'; \ *(array[1]) = '3'; \ *(*(array+1)+1) = '4'; \ *(array[0]+3) = '5'; \ *(*array+2) = '7'; \ array[0][1] = '6'; void multi_01( char (*array)[NUMCOLUMNS] ) { FILL_ARRAY(); } void multi_02( char array[][NUMCOLUMNS] ) { FILL_ARRAY(); } void multi_03( char array[NUMROWS][NUMCOLUMNS] ) { FILL_ARRAY(); } void multi_04( char **array ) { FILL_ARRAY(); } void multi_05( char *array[] ) { FILL_ARRAY(); } void multi_06( char *array[NUMCOLUMNS] ) { FILL_ARRAY(); } int main(int argc, char **argv) { int i; char mystr[NUMROWS][NUMCOLUMNS] = { { 'X', 'X', 'X', 'X'}, {'X','X','X'} }; char *pmystr[sizeof(mystr)/sizeof(*mystr)]; int numcolumns = sizeof(*mystr); int numrows = sizeof(mystr)/sizeof(*mystr); for( i=0; i 

您应该将栏定义为:

 bar( int* matrix ) 

在C中,所有数组都应该作为int* (或其他类型的type_of_element* )传递。

如果你的数据真的是一个指针数组,那么int **就可以了。 int[*data[]例如。 这就是你在main(int argc, char *argv[])得到的东西main(int argc, char *argv[])

 int **matrix 

表示你有一个指向int的指针。 这通常用于指示指向指针数组(也称为向量)的指针。 绝对不是这样的

 int matrix[10][10] 

这是一个指向单个内存部分的指针,大小为10×10整数。 尝试更改为:

 void bar(int *matrix[])