C语言 分配给指针时从不兼容的指针类型警告初始化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44523828/
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
Initialization from incompatible pointer type warning when assigning to a pointer
提问by Nathu
GCC gives me an 'Initialization from incompatible pointer type' warning when I use this code (though the code works fine and does what it's supposed to do, which is print all the elements of the array).
当我使用此代码时,GCC 给了我一个“从不兼容的指针类型初始化”警告(尽管代码工作正常并且执行它应该做的事情,即打印数组的所有元素)。
#include <stdio.h>
int main(void)
{
int arr[5] = {3, 0, 3, 4, 1};
int *p = &arr;
printf("%p\n%p\n\n", p);
for (int a = 0; a < 5; a++)
printf("%d ", *(p++));
printf("\n");
}
However no warning is given when I use this bit of code
但是当我使用这段代码时没有给出警告
int main(void)
{
int arr[5] = {3, 0, 3, 4, 1};
int *q = arr;
printf("%p\n%p\n\n", q);
for (int a = 0; a < 5; a++)
printf("%d ", *(q++));
printf("\n");
}
The only difference between these two snippets is that I assign *p = &arr and *q = arr .
这两个片段之间的唯一区别是我分配了 *p = &arr 和 *q = arr 。
- Exactly what different is the & making ?
- And why does the code execute and give the exact same output in both the cases ?
- &making 到底有什么不同?
- 为什么代码在两种情况下都执行并给出完全相同的输出?
回答by Lundin
&arrgives an array pointer, a special pointer typeint(*)[5]which points at the array as whole.arr, when written in an expression such aint *q = arr;, "decays" into a pointer to the first element. Completely equivalent toint *q = &arr[0];
&arr给出一个数组指针,一种特殊的指针类型int(*)[5],它指向整个数组。arr, 当写成这样的表达式 a 时int *q = arr;,“衰减”为指向第一个元素的指针。完全相当于int *q = &arr[0];
In the first case you try to assign a int(*)[5]to a int*. These are incompatible pointer types, hence the compiler diagnostic message.
在第一种情况下,您尝试将 a 分配int(*)[5]给 a int*。这些是不兼容的指针类型,因此是编译器诊断消息。
As it turns out, the array pointer and the int pointer to the first element will very likely have the same representation and the same address internally. This is why the first example "works" even though it is not correct C.
事实证明,指向第一个元素的数组指针和 int 指针很可能在内部具有相同的表示形式和相同的地址。这就是为什么第一个例子“有效”,即使它不正确 C。
回答by SHG
These are the ways to point to a (beginning of) array (without a warning), both work:
这些是指向(开始)数组(没有警告)的方法,两者都有效:
int *q = arr;
/* OR */
int *q = &arr[0];
This one is something in between, and will generate a warning:
这个介于两者之间,会产生警告:
int *q = &arr;
回答by Sourav Ghosh
TL;DRCheck the types.
TL;DR检查类型。
&arris of typeint (*) [5](pointer to an array of 5ints).arris of typeint [5], but not always.
&arr是类型int (*) [5](指向 5ints数组的指针)。arr是类型int [5],但并非总是如此。
Quoting C11, chapter §6.3.2.1, (emphasis mine)
引用C11,第 6.3.2.1 章,(强调我的)
Except when it is the operand of the
sizeofoperator, the_Alignofoperator, or the unary&operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type''is converted to an expression with type ‘‘pointer to type''that points to the initial element of the array objectand is not an lvalue.
除非它是运算
sizeof符的操作数、运算_Alignof符或一元运算&符,或者是用于初始化数组的字符串文字,否则类型为“array of type”的表达式将转换为类型为“”的表达式指向类型'' 的指针指向数组对象的初始元素并且不是左值。
hence,
因此,
int *q = arr; // int[5] decays to int *, == LHS
and
和
int *q = &arr[0]; // RHS == LHS
are same, whereas,
是相同的,而,
int *q = &arr; // LHS (int *) != RHS (int (*) [5])
is a mismatched type expression.
是不匹配的类型表达式。
Now, it works, because, as already mentioned in Lundin's answer, the address of the array variable is likely to be the same as the address of the first element of the array, so despite the type mismatch, the valueis same, so this seems to work.
现在,它起作用了,因为正如在Lundin's answer 中已经提到的,数组变量的地址很可能与数组的第一个元素的地址相同,所以尽管类型不匹配,但值是相同的,所以这个似乎工作。
回答by TomServo
The output is the same because the address of arr[0]is literally equivalent to the pointer to arr[]. Any pointer initialized to point to arr[0]will have as its value the address of arr[0]; that's what a pointer is. Read up on pointer and especially on their relationship to arrays. The are countless tutorials out there, some of which probably show your two cases as examples.
输出是相同的,因为 的地址在arr[0]字面上等同于指向 的指针arr[]。任何初始化为指向的指针arr[0]的值都为arr[0]; 这就是指针。阅读指针,尤其是它们与数组的关系。那里有无数的教程,其中一些可能以您的两个案例为例。
回答by Serge Ballesta
When used in an expression as an lvalue, an array decaysto a pointer to its first element. So int *q = arr;initializes int pointer qwith the address of the first element of the array arr: all is fine and no warning is emited.
当在表达式中用作左值时,数组衰减为指向其第一个元素的指针。所以用数组的第一个元素的地址int *q = arr;初始化 int 指针:一切都很好,没有发出警告。qarr
But &arris the address of an array. It could only be used correctly to initialize (or assign to) a pointer to array or same size, or a pointer to an array of undeterminated size. You use it to initialize a pointer to int (which is a different and non compatible type) and the compiler warns you about that. Because using a pointer initialized from a pointer to a different type is Undefined Behaviour according to the standard.
但是&arr是一个数组的地址。它只能正确地用于初始化(或分配给)指向数组或相同大小的指针,或指向未确定大小的数组的指针。您使用它来初始化一个指向 int 的指针(这是一种不同且不兼容的类型),编译器会就此警告您。因为根据标准,使用从指向不同类型的指针初始化的指针是未定义行为。
But on common implementations, pointers to any type have the same representation which is the address of the first byte of the object. So even if it is not allowed by the standard, the instruction int *p = arr;ends with the same value for pas would give the correct int *p = arr;. That explains why your program still gives the expected value.
但是在常见的实现中,指向任何类型的指针都具有相同的表示形式,即对象的第一个字节的地址。因此,即使标准不允许,指令也会int *p = arr;以p与给出正确的int *p = arr;. 这解释了为什么您的程序仍然提供预期值。
BTW, Undefined Behaviour does not forbid expected result, simply a different compiler could give different results, crash, prematurely ends without error, kick your dog, etc. (even if no compiler could hit my dog till now ;-) )
顺便说一句,未定义的行为不禁止预期的结果,只是不同的编译器可能会给出不同的结果,崩溃,过早结束而没有错误,踢你的狗等等(即使到目前为止没有编译器可以击中我的狗;-))

