我有以下签名的功能:
void box_sort(int**, int, int)
以及以下类型的变量:
int boxes[MAX_BOXES][MAX_DIMENSIONALITY+1]
当我调用函数
时box_sort(boxes, a, b)
GCC给了我两个警告:
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中的类型不同?
答案 0 :(得分:13)
我知道几天前几乎有一个类似的问题......但现在找不到它。
答案是,int[size][]
(见底部注释)和int**
绝对不是同一类型。在许多情况下,您可以互换使用int[]
和int*
,特别是在这种情况下,因为当您将数组传递给函数时,数组会衰减到指向第一个元素的指针。但对于二维数组,这些是非常不同的存储方法。
这是他们在2x2阵列的内存中看起来的样子:
int a[2][2]:
__a[0][0]__|__a[0][1]__|__a[1][0]__|__a[1][1]__
(int) (int) (int) (int)
int **a (e.g. 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[][]
不是真正的类型;只有一种尺寸可以不指定。但问题的核心是二维数组和双指针是否相同。
答案 1 :(得分:1)
您从未根据签名要求构建指针数组。
在C中有两种方法可以做二维数组。在一种情况下,你只需要很多东西,并告诉编译器维度是什么。它通过将行索引乘以列数来计算行的开头,然后添加列索引以查找该行中的元素。
另一种方法是使用指针向量,其中编译器只是取消引用向量以找到行的开头,但编译器不会自动为您生成这些,您必须自己完成。
您的实际对象是第一种,但您的函数原型要求第二种。
所以你应该改变原型以匹配对象,或者构造一个行指针向量来传递给函数。
答案 2 :(得分:1)
C中没有int[][]
这样的类型,只能指定多维数组的第一部分。所以int[][5]
没问题。
除了此处发布的其他答案外,如果您可以使用C99,您可以使用变量数组来完成您想要的任务:
void box_sort(int N, int M, int x[M][N]);
这将适用于除Microsoft的Visual C ++之外的大多数平台。
答案 3 :(得分:0)
当数组表达式出现在大多数上下文中时,其类型将从“N元素数组T”隐式转换为“指向T”,其值设置为数组中第一个元素的地址。此规则的例外情况是,数组表达式是sizeof
或地址 - (&
)运算符的操作数,或者数组表达式是用于初始化另一个数组的字符串文字。声明。
在代码的上下文中,这意味着在您致电box_sort
时,表达式boxes
的类型会隐式转换为M-element array of N-element array of int
到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数组并手动计算偏移量。