C 数组不兼容指针类型

C 数组不兼容指针类型,c,arrays,pointers,C,Arrays,Pointers,有人能告诉我b/w的区别吗 int vector[]={10,20,30} int *p = vector 及 我知道通过提到数组名,我们可以得到它的基址。第二个声明给了我警告 从不兼容的指针类型初始化 为什么警告,这两个语句都给出了数组基址 在表达式中使用时,数组名在大多数情况下会衰减为指向其第一个元素的指针 因此: int *p = vector; 相当于: int *p = &vector[0]; &vector[0]的类型是int*,因此该类型是兼容的 当数组是运算符&地址

有人能告诉我b/w的区别吗

int vector[]={10,20,30}
int *p = vector

我知道通过提到数组名,我们可以得到它的基址。第二个声明给了我警告

从不兼容的指针类型初始化


为什么警告,这两个语句都给出了数组基址

在表达式中使用时,数组名在大多数情况下会衰减为指向其第一个元素的指针

因此:

int *p = vector;
相当于:

int *p = &vector[0];
&vector[0]
的类型是
int*
,因此该类型是兼容的

当数组是运算符
&
地址的对象时,数组不衰减的少数情况之一。然后
&array
是数组的地址,其类型为
int(*)[3]
,即指向大小为3的数组的指针。这与
int*
不兼容,因此出现错误


虽然数组的地址和它的第一个元素的地址具有相同的值,但它们的类型不同。

&vector
的类型是
int(*)[3]
即指向数组的指针,而没有
&
vector
将衰减为指向第一个元素的
int*

int(*)[3]
,即使指向同一地址与
int*
不兼容,因此您的程序存在约束冲突,这使您的程序成为无效程序,并且编译器必须发出诊断消息

C标准在[footnote()中明确提到允许编译器成功编译无效程序:

9) 其目的是一个实现应该识别每个违规的性质,并在可能的情况下进行本地化。当然,只要有效程序仍然正确翻译,一个实现就可以自由生成任意数量的诊断。它还可以成功翻译无效程序。


也就是说,只要正确翻译了有效的程序,编译器就可以对给定的源代码执行任何它喜欢的操作。因此,许多编译器将使用默认设置来查看这些类型的内容,并提供或多或少具有预期或同样意外结果的翻译,您将l get只有一个警告

C中的表达式既有值也有类型

给定
int vector[]={10,20,30};
vector
是一个数组。C有一条规则,当数组在某个位置1之外的表达式中使用时,它会自动转换为指向其第一个元素的指针。然后,它的值实际上是数组2开头的地址,它的类型是“指向
int
”的指针

表达式
&vector
获取数组的地址。这与它的第一个元素的地址不同。很大程度上,它们都有相同的值。数组和它的第一个元素都从内存中相同的位置开始。但是它们有不同的类型。
&vector
的类型是“指向数组的指针3
int

C有关于类型的规则,您不能在需要另一种类型的情况下自动使用一种类型。有时类型会自动转换,例如当较窄的整数转换为较宽的整数时。但是,通常在类型对软件的含义很重要的地方,没有自动转换(或有限的转换)。如果您试图将指向数组的指针指定给指向
int
的指针,一个好的编译器将警告您正在执行不正确的操作

当指向一种类型的指针被分配给指向另一种类型的指针时,可能是因为程序员犯了错误。这就是编译器警告您的原因

此外,不同类型的相同值的行为可能不同。因为
数组
是指向其第一个元素的指针,
a+1
是指向第二个元素的指针。但是,由于
&array
是指向数组的指针,
&array+1
是指向数组末尾的指针(如果存在阵列,则它后面的下一个阵列将在其中启动)

脚注 1当数组是
sizeof
的操作数或一元
&
的操作数,或者是用于初始化数组的字符串文字时,数组不会自动转换


2当然,数组的起始位置与它的第一个元素的起始位置相同。因此它们具有相同的虚拟地址。因此它们具有相同的值。但是,C指针存在一些技术问题,这意味着指向同一位置的两个指针可能不完全“相同”在某些意义上。在这个回答中,我将不深入讨论这个问题。我们可以将指向同一位置的指针视为本次讨论中的指针。

不是“一个好的编译器”-根据定义,不发出警告的编译器不是C编译器。@AnttiHaapala:尽管如此,它还是一个编译器。大多数编译器都不是C编译器。@P.P.:C 2018 6.5.16.1指定了分配约束,如果将指向数组的指针分配给指向
int
的指针,则会违反该约束。C 2018 5.1.1.3需要一个一致的实现o如果违反约束,则生成诊断。因此,不生成此类诊断的软件不是符合C标准的实现。当然,GCC是(接近)C编译器只有
-pedantic
和最近的另一个问题一样,当使用不等式运算符将
double*
0
进行比较时,它不会产生任何诊断:(@P.P.:这是Antti Haapala的评论所说的,如果编译器不产生诊断,它就不是C编译器。
int *p = &vector[0];