C 数组不兼容指针类型
有人能告诉我b/w的区别吗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*,因此该类型是兼容的 当数组是运算符&地址
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
的类型是“指向数组的指针3int
”
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];