首先我们来看一下它们分别的定义方式:
指针数组:int* p[5];
数组指针:int (*p)[5];
函数指针:int (*p)(int,int);
函数指针数组:int(p[5])(int x, int y);
函数指针数组的指针:int ((*p)[5])(int x,int y);
指针数组是数组,是一个存放指针的数组
数组指针是指针,是一个指向数组的指针
函数指针是指针,是一个指向函数的指针
函数指针数组是数组,是一个存放函数地址的数组
函数指针数组的指针是指针,是一个指向 函数指针数组 的指针
关于优先级的问题:
[] 的优先级高于 * ,而 ()的优先级高于[] 。
一、指针数组:
int* p[5] ,[]的优先级比较高,因此[]和p先结合,因此p是(int*)类型的,是一个整型指针的数组。
我们来看一段代码:
int a=1,b=2;
int *p[2]; //定义指针数组
p[0]=&a; //给数组第一个元素赋值为a的地址
p[1]=&b; //给数组第二个元素赋值为b的地址
printf("p[0]=%p, &a=%p\n",p[0],&a); //输出第一个数组第一个元素,与a地址比较
printf("p[1]=%p, &b=%p\n",p[1],&b);
printf("*p[0]=%d, a=%d\n",*p[0],a); //输出数组第一个元素的值
printf("*p[1]=%d,b=%d\n",*p[1],b);
运行结果:
我们可以看到:p[0],p[1]输出的结果是两个地址,*p[0] 和 p[1] 是两个整数,因此指针数组存放的是地址,这里定义的intp[2],就只能存放int类型的数据的地址。
—>>指针数组还有一个很重要的用处就是用来指向 二维数组的第一维,为什么呢?因为指针数组的本质是数组,数组中的元素是指针类型,而二维数组中的第一维是一维数组的首地址,类型匹配可以用指针类型指向。
int a[2][3]={{1,2,3},{4,5,6}};
int i,j;
int *p[2];
p[0]=a[0];
p[1]=a[1];
for(i=0;i<2;i++)
{
for(j=0;j<3;j++,p[i]++)
printf("%3d",*p[i]);
printf("\n");
}
return 0;
二、数组指针
int (*p)[5] ,()的优先级比[]的优先级高,所以p先与 * 结合,因此p是一个指针,而这个指针指向了int类型的长度为5的一个数组,它就是整型数组的指针。(int (*p)[5],我们不妨将它写成 int[5]*p是不是就更好理解了呢,这样表示可以帮助我们理解,但是编译不能这样写,因为编译器不认识。)
int main(){
int arr[4] = {0};
arr;//表示数组首元素的地址
&arr;//表示数组的地址
// 具 体 差 异 在 哪 ? ?
printf("arr=%p\n", arr);
printf("&arr=%p\n",&arr);
printf("arr+1=%p\n", arr+1);
printf("&arr+1=%p\n", &arr+1);
//我们可以看出产生的结果是截然不同的
//这是因为数组的地址和数组首元素的地址值是相同的,但是意义不同。
int (*p)[4];
//p是int类型的数组的指针,存放数组地址,那么
//p=arr; //会报错
p=&arr;
printf("p=%p\n",p);
printf("p+1=%p\n",p+1);
return 0;
}
运行结果:
在这里我们可以看到,arr和&arr表示的地址是一样的,但是+1的结果却有不同,这是因为,arr表示数组首元素的地址,而&arr表示的是数组的地址,arr+1则表示第二个元素的地址,增加int类型的4个字节,而&arr+1,整个数组的地址加一,总共4个元素,4*4=16个字节。在16进制中,0018FF38+16=0018FF48。
int (*p)[4],定义了了一个指向int类型的长度为4的 指针变量,这里赋值只能将&arr也就是整个数组的地址给它,当赋值p=arr时,程序会报错,也正是因为,p存放的整个数组的地址,而arr只表示首元素的地址。p+1的值与&arr+1的值也就相同。
我们再来看一段代码:
int array[2][3] =
{
{ 0, 1, 2 },
{ 3, 4, 5 }
};
//指针数组
int *p[2][3];
//用了两层for循环遍历这个二维数组,将数组每个元素的地址赋给指针数组的每一个元素
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
p[i][j] = &array[i][j];
}
}
//遍历指针数组 *p[i][j] 输出数组p中每个元素的值
for ( i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", *p[i][j]);
}
printf("\n");
}
//数组指针
int (*q)[3] = array;
for ( i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", q[i][j]);
}
printf("\n");
}
return 0;
}
运行结果:
同样是二维数组赋值并输出,指针数组却用了两次两层的for循环,第一次将原二维数组的地址赋给指针数组的每个元素,第二次是取地址的的值将其循环输出。
然而,定义的数组指针却能够通过int (*q)[3] = array;就获得原二维数组的值,这是因为我们将array[2][3]看作一个2个具有三个元素的一维数组,这里的array表示的是第一行元素的地址,相当于一个一维数组,因此能够直接赋值给p。