数组名,数组首地址,a,&a,&a[0]
(1)指针数组: 是数组,但数组中的每个元素都是指针
int *p[5];//如p[2]是指针,可*p[ 2]=3;
(2)指向数组的指针: 是个指针,但它指向的是一个数组
int a[5];
int (*p)[5];//与前一行比较,*p相当于a,即p=&a;就像:int m;int *pm;//*pm就相当于m.pm=&m;
p= &a;//可与前一行合并为int (*p)[5]=&a;
a代表这个数组,它是一个指针,指向第一个元素
这里一定要记住,a是数组名,&a代表的不是取a这个变量的地址,而是取数组元素的地址
a 的类型是 int[5] 数组
&a 的类型是 int(*)[5] 指针——指向int[5]数组的指针
&a[0] 的类型是 int * 指针——指向int类型的指针。
sizeof(a)=20;
sizeof(*a)=4; 因为有取值符*,表示把a当成一个指针(int*),而a指向数组的首地址,
即a=&(a[0]),即sizeof(*a)=sizeof(*&(a[0]))=sizeof(a[0])=sizeof(int)=4。
sizeof(*&a)=20;//因为p=&a,所以=sizeof(*p),而*p=a,所以=sizeof(a)=20;
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));//输出:2,5
指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同,指针只是一个内存地址,但指针指向地址的长度可能不同,如char *pc
与int *pi
,sizeof(pc)=sizeof(pi)=4
,但为什么输出时,cout<<*pc
只从内存处取一个字符,而cout<<*pi
则从内存处取4个字符,这是由指针类型(char,int)
决定的.对A* p;p+1=(A*)
(p的地址值+sizeof(A)),如pc+1=pc+sizeof(char)=(char*)
(pc的地址值+1个字节),而pi+1=pi+sizeof(int)=(int*)
(pi的地址值+4个字节).
对代码中的&a+1
,&a
是数组指针,其类型为int (*)[5]
,因为p=&a
,也即是p的类型.所以&a+1=&a+sizeof(A)
,其中A为int[5]:(把A=int[5]
代入A* p
,即相当于int(*p)[5])
. 所以&a+1=&a
的地址值+54字节,即变为数组a的结束地址的下一个地址(即&a[5]
),&a+1
仍是int (*)[5]
类型,经(int *)(&a+1)
强制转化为int,赋值给ptr.后面的ptr-1=ptr-sizeof(int)=ptr
的地址值-4个字节,即变为数组a的最后一个元素的地址&a[4],*(ptr-1)
即为a[4],故输出为5.
而a+1=a+sizeof(int)
:(此处a退化为int*
,故对于A* p
,A为int)=a的地址值+4个字节,即是&a[1]
,则*(a+1)
即a[1],故输出2.
又如:
double t[]={1, 2, 578, 111,90} ;
double *pt= &t[3];//指向值为111
int *ptInt= reinterpret_cast< int * > (pt);
char *ptCh= reinterpret_cast< char * > (pt);
cout<< *( pt- 1)<< "\t"<< *(reinterpret_cast<double*>(ptInt-2))<<"\t"<<
*(reinterpret_cast<double*>(ptCh-8));//最后输出结果全为578
void Fun( int *p)
与void Fun( int p[])
是一样的,即函数列表中的数组此时退化成了指针
相关链接:
指针函数与函数指针的区别
数组名,数组首地址,a,&a,&a[0]