指针类型不兼容

时间:2010-03-29 17:13:10

标签: c gcc

我有以下签名的功能:

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中的类型不同?

4 个答案:

答案 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 intpointer 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数组并手动计算偏移量。