将数组和矩阵传递给函数作为指针和指向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[])