C++ 为什么*(pa-1)的输出是'a'的最后一个元素?
我从下面代码的输出中得到的是C++ 为什么*(pa-1)的输出是'a'的最后一个元素?,c++,C++,我从下面代码的输出中得到的是*(pa-1)=5:为什么 #include<iostream> using namespace std; int main(){ int a[5]={1,2,3,4,5}; int *pa=(int *)(&a+1); cout<<"*(pa-1)="<<*(pa-1)<<endl; } #包括 使用名称空间std; int main(){ int a[5]={1,2,3,4
*(pa-1)=5
:为什么
#include<iostream>
using namespace std;
int main(){
int a[5]={1,2,3,4,5};
int *pa=(int *)(&a+1);
cout<<"*(pa-1)="<<*(pa-1)<<endl;
}
#包括
使用名称空间std;
int main(){
int a[5]={1,2,3,4,5};
int*pa=(int*)(&a+1);
cout&a
是数组的地址,它的类型为“指针指向-int[5]
”。因此&a+1
前进五个点的整个数组,刚好经过数组
pa
是一种类型双关指针*,它现在将同一地址视为整数数组(而不是数组!)中的地址。因此,它与结束指针a+5
之后的地址相同。减1表示数组中最后一个元素的指针,即5
*)这种类型的双关是可以接受的,只要数组的底层类型是标准布局(即int
),它就可以满足您的要求。您还需要什么?&a
具有类型int(*)[5]
,因此&a+1
点
到a
之后的下一个int[5]
;它是
迭代int[5]
元素。然后将其重新解释为
int*
,并访问它。正式地说,我认为您的代码没有定义
行为,因为这是你唯一可以合法处理结果的事情
一个重新解释的类型是将其转换回原始类型。
(在涉及到字符类型指针的情况下也有例外。)
在实践中,各种要求贯穿于整个标准
这意味着您将获得a
中最后一个int
的地址,因为您正在将指向int数组的指针强制转换为指向int@DanF:只要T
是标准布局,(T*)[N]
可转换为T*
,并给出第一个元素的地址。数组是特殊的:a
是它自己的地址,&a
=a
-虽然类型不同。写得不错。@RichardSitze:是的,很多东西都有相同的地址。是类型和值对指定了唯一的对象。您可以很容易地列出一长串降序子对象,这些子对象也都有相同的地址。@RichardSitze,C标准并不禁止使用运算符的地址获取指向数组的指针,它会生成类型(*)的指针[N]
。答案是正确的。@HristoIliev:我不认为Richard在抱怨。他只是指出数组是唯一的,因为变量名本身可以充当与对象地址相同值的地址,尽管类型不同。他可能应该说(void*)(a)==(void*)(&a)
,尽管:-)@RichardSitze与我所见过的任何东西(包括标准)都不符。a
的类型是int[5]
。&a
的类型是int(*)[5]
(int*)[5]
不是合法的类型表达式。&a
的类型是int(*)[5]
,一个指向5个int
数组的指针。类型是int(*)[5]
。语法见C99标准的§6.7.6。@KerrekSB修复了它:-)。(我想我一定是在发布之前意外地错编了一些内容。可能是a
有typeint[5]
,所以&a
有typeint(*)[5]
)可以肯定的是,我认为这不是UB,因为当类型为标准布局时,允许将指向对象的指针视为指向第一个成员或元素的指针。@KerrekSB这可能在C++11中发生了更改。至少在之前,这是未定义的行为:C标准是精心设计的,以允许“fat”指针,包括边界信息(也可能是一些类型信息),以便完全检查实现是可能的。早期C++也允许这样做,并且至少有一个编译器在过去实现它。