C语言 不兼容的指针类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2539844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Incompatible pointer type
提问by Boffin
I have the function with following signature:
我有以下签名的功能:
void box_sort(int**, int, int)
and variable of following type:
和以下类型的变量:
int boxes[MAX_BOXES][MAX_DIMENSIONALITY+1]
When I am calling the function
当我调用函数时
box_sort(boxes, a, b)
GCC gives me two warnings:
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)
The question is why? Whether int x[][] and int** x (and actually int* x[]) are not the same types in C?
问题是为什么?int x[][] 和 int** x(实际上是 int* x[])在 C 中是否不是相同的类型?
回答by Cascabel
I know there was a question almost exactly like this a couple days ago... can't find it now though.
我知道几天前有一个几乎完全相同的问题……但现在找不到了。
The answer is, int[size][](see note at the bottom) and int**are definitely not the same type. You can use int[]and int*interchangeably in many cases, in particular in cases like this because the array decays to a pointer to the first element when you pass it into a function. But for a two-dimensional array, these are very different methods of storing.
答案是,int[size][](请参阅底部的注释)并且int**绝对不是同一类型。在许多情况下,您可以交替使用int[]和int*,特别是在这种情况下,因为当您将数组传递给函数时,数组会衰减为指向第一个元素的指针。但是对于二维数组,这些是非常不同的存储方法。
Here's what they'd look like in memory for a 2x2 array:
以下是 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)
You could construct the second one like this:
你可以像这样构造第二个:
int **a = malloc(2 * sizeof(int*));
a[0] = malloc(2 * sizeof(int));
a[1] = malloc(2 * sizeof(int));
Note: As others have noted, int[][]isn't a real type; only one of the sizes can be unspecified. But the core of the question here is whether a two-dimensional array and a double pointer are the same thing.
注意:正如其他人所指出的,int[][]不是真正的类型;只有一种尺寸可以是未指定的。但是这里问题的核心是二维数组和双指针是否是同一个东西。
回答by DigitalRoss
You never constructed an array of pointers as the signature requires.
您从未按照签名要求构造指针数组。
There are two ways to do 2D arrays in C. In one case, you just have a lot of something and the compiler is told what the dimensions are. It calculates the beginning of the row by multiplying the row index by the number of columns and then it adds the column index to find the element within that row.
在 C 中有两种方法可以做二维数组。在一种情况下,你只有很多东西,编译器会被告知维度是什么。它通过将行索引乘以列数来计算行的开头,然后添加列索引以查找该行中的元素。
The other way is with a vector of pointers, where the compiler just dereferences the vector to find the beginning of the row, but the compiler won't make these for you automatically, you have to do it yourself.
另一种方法是使用指针向量,编译器只是取消引用向量以找到行的开头,但编译器不会自动为您制作这些,您必须自己做。
Your actual object is one of the first kind, but your function prototype is asking for the second kind.
您的实际对象是第一种,但您的函数原型要求第二种。
So you should either change the prototype to match the object or construct a vector of row pointers to pass to the function.
因此,您应该更改原型以匹配对象,或者构造一个行指针向量以传递给函数。
回答by Dietrich Epp
There is no such type in C as int[][], only the first part of a multidimensional array can be unspecified. So int[][5]is okay.
C 中没有像 那样的类型int[][],只有多维数组的第一部分可以是未指定的。所以int[][5]没问题。
In addition to the other answers posted here, if you can use C99, you can use variable arrays to accomplish what you want:
除了此处发布的其他答案之外,如果您可以使用 C99,则可以使用变量数组来完成您想要的操作:
void box_sort(int N, int M, int x[M][N]);
This will work on most platforms except Microsoft's Visual C++.
这将适用于除 Microsoft 的 Visual C++ 之外的大多数平台。
回答by John Bode
When an array expression appears in most contexts, its type is implicitly converted from "N-element array of T" to "pointer to T", and its value is set to the address of the first element in the array. The exceptions to this rule are when the array expression is an operand of the sizeofor address-of (&) operators, or if the array expression is a string literal being used to initialize another array in a declaration.
当数组表达式出现在大多数上下文中时,其类型会从“T 的 N 元素数组”隐式转换为“指向 T 的指针”,并将其值设置为数组中第一个元素的地址。此规则的例外是当数组表达式是sizeofor address-of ( &) 运算符的操作数时,或者数组表达式是用于初始化声明中的另一个数组的字符串文字时。
What this means in the context of your code is that in your call to box_sort, the type of the expression boxesis implicitly converted from M-element array of N-element array of intto pointer to N-element array of int, or int (*)[MAX_DIMENSIONALITY+1], so your function should be expecting parameter types like:
在您的代码上下文中,这意味着在您调用 时box_sort,表达式的类型boxes从M-element array of N-element array of inttopointer to N-element array of int或隐式转换int (*)[MAX_DIMENSIONALITY+1],因此您的函数应该期待参数类型,例如:
void box_sort(int (*arr)[MAX_DIMENSIONALITY+1], int x, int y)
{
...
}
Since int *aand int a[]are synonymous in a function parameter declaration, it follows that int (*a)[N]is synonymous with int a[][N], so you could write the above as
由于int *a和int a[]在函数参数声明中int (*a)[N]是同义词int a[][N],因此它与 同义词,因此您可以将上述内容写为
void box_sort(int arr[][MAX_DIMENSIONALITY+1], int x, int y)
{
}
although I personally prefer the pointer notation, as it more accurately reflects what's going on. Note that in your function, you would subscript arras normal:
虽然我个人更喜欢指针符号,因为它更准确地反映了正在发生的事情。请注意,在您的函数中,您会arr像往常一样下标:
arr[x][y] = ...;
since the expression arr[x]is equivalent to *(arr + x), the pointer is implicitly dereferenced.
由于表达式arr[x]等价于*(arr + x),指针被隐式取消引用。
If you want box_sort to work on arbitrarily-sized arrays (i.e., arrays where the second dimension isn't necessarily MAX_DIMENSIONALITY+1), then one approach is to do the following:
如果您希望 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] = ...;
}
Basically, you're treating boxesas a 1-d array of int and calculating the offsets manually.
基本上,您将其boxes视为一维 int 数组并手动计算偏移量。

