指针类型不兼容

我有以下签名的function:

void box_sort(int**, int, int) 

和以下类型的变量:

 int boxes[MAX_BOXES][MAX_DIMENSIONALITY+1] 

当我调用该函数时

 box_sort(boxes, a, b) 

海湾合作委员会给了我两个警告:

 103.c:79: warning: passing argument 1 of 'box_sort' from incompatible pointer type (string where i am calling the function) 103.c:42: note: expected 'int **' but argument is of type 'int (*)[11] (string where the function is defined) 

问题是为什么 ? int x [] []和int ** x(实际上是int * x [])是否与C中的类型不同?

我知道几天前有一个几乎完全像这样的问题……但现在找不到它。

答案是, int[size][] (见底部注释)和int**绝对不是同一类型。 在很多情况下,你可以互换地使用int[]int* ,特别是在这种情况下,因为当你将数组传递给函数时,数组会衰减到指向第一个元素的指针。 但对于二维数组,这些是非常不同的存储方法。

这是他们在2x2arrays的内存中的样子:

 int a[2][2]: __a[0][0]__|__a[0][1]__|__a[1][0]__|__a[1][1]__ (int) (int) (int) (int) int **a (eg dynamically allocated with nested mallocs) __a__ (int**) | v __a[0]__|__a[1]__ (int*) (int*) | | | | v ------------------> __a[0][0]__|__a[0][1]__ __a[1][0]__|__a[1][1]__ (int) (int) (int) (int) 

您可以像这样构建第二个:

 int **a = malloc(2 * sizeof(int*)); a[0] = malloc(2 * sizeof(int)); a[1] = malloc(2 * sizeof(int)); 

注意:正如其他人所说, int[][]不是真正的类型; 只有一种尺寸可以不指定。 但问题的核心是二维数组和双指针是否相同。

您从未构造过签名所需的指针数组。

在C中有两种方法可以做二维数组。在一种情况下,你只需要很多东西,并告诉编译器维度是什么。 它通过将行索引乘以列数来计算行的开头,然后添加列索引以查找该行中的元素。

另一种方法是使用指针向量,编译器只是取消引用向量以找到行的开头,但编译器不会自动为您生成这些,您必须自己完成。

你的实际对象是第一种,但是你的函数原型要求第二种。

因此,您应该更改原型以匹配对象,或者构造行指针的向量以传递给函数。

在C int[][]没有这样的类型,只能指定多维数组的第一部分。 所以int[][5]没问题。

除了这里发布的其他答案,如果你可以使用C99,你可以使用变量数组来完成你想要的:

 void box_sort(int N, int M, int x[M][N]); 

这将适用于除Microsoft的Visual C ++之外的大多数平台。

当数组表达式出现在大多数上下文中时,其类型将从“N元素数组T”隐式转换为“指向T”,其值设置为数组中第一个元素的地址。 此规则的例外情况是,数组表达式是sizeof或address-of( & )运算符的操作数,或者数组表达式是用于初始化声明中的另一个数组的字符串文字。

这意味着在你的代码上下文中,在你对box_sort的调用中,表达式boxes的类型被隐式地从M-element array of N-element array of int转换为pointer to N-element array of int M-element array of N-element array of int pointer to N-element array of intint (*)[MAX_DIMENSIONALITY+1] pointer to N-element array of int int (*)[MAX_DIMENSIONALITY+1] ,所以你的函数应该期望参数类型如:

 void box_sort(int (*arr)[MAX_DIMENSIONALITY+1], int x, int y) { ... } 

由于int *aint a[]在函数参数声明中是同义的,因此int (*a)[N]int a[][N]同义,因此您可以将上面的内容写为

 void box_sort(int arr[][MAX_DIMENSIONALITY+1], int x, int y) { } 

虽然我个人更喜欢指针符号,因为它更准确地反映了正在发生的事情。 请注意,在您的函数中,您可以正常下标arr

 arr[x][y] = ...; 

因为表达式arr[x]等价于*(arr + x) ,所以指针被隐式解除引用。

如果您希望box_sort在任意大小的数组上工作(即第二维不一定是MAX_DIMENSIONALITY + 1的数组),那么一种方法是执行以下操作:

 int boxes[X][Y]; ... box_sort (&boxes[0], X, Y, x, y); ... void box_sort(int *arr, size_t rows, size_t cols, int x, int y) { ... arr[x*cols + y] = ...; } 

基本上,您将boxes视为int的一维数组并手动计算偏移量。