指针类型不兼容
我有以下签名的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 int
或int (*)[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 *a
和int 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的一维数组并手动计算偏移量。