数组名,数组首地址,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 *pcint *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]