指针数组
顾名思义,是一个数组,类似于整型数组是由整型组成的数组,那么指针数组就是由指针组成的数组。书写格式如下:
int*p[10];
char*p[10];
因为[ ] 的优先级比 * 高,所以变量p先与 [ ] 结合表示他是一个数组,数组大小为10。然后再与 int* 结合表示数组里面存储的是整型指针,当然 char* 存储的就是字符指针。
类似于整型数组指针
int a; //这是一个整型变量
int a[10]; //变量a先与[]结合 这是一个数组 存储整型
int* p; //这是一个整型指针变量
int* p[10]; // 变量p先与 [] 结合 再与int*结合 这是一个数组 存储整型指针
数组指针
显然这是一个指针,先来看一下它的书写格式:
int(*p)[10];
char(*p)[10];
由于加了 ( ) ,优先级发生改变,变量p先与 * 结合,代表它是一个指针,再与int[10]结合,说明它指向一个存有十个整形的数组的地址。类似于:
int* p; //p与*结合,代表它是指针,指向存有int整型的地址
int(*p)[10];
函数指针
函数指针也是一个指针,它指向一个函数的地址。首先我们定义一个函数,再让一个指针指向它:
void test1()
{
printf("hello\n");
}
int test2(int x,int y);
{
return x+y;
}
int main()
{
void(*p1)() = &test1; //函数指针的定义与赋值
int(*p2)(int,int) = test2;
}
可以看到函数指针和函数数组类似,()的优先于高,变量先与 * 结合表示它是一个指针,再将对应的函数返回值和参数类型添加进去,就组成了函数指针。
在使用函数指针的时候,以上面为例没有参数的可以直接test1()进行调用,有参数的test2(5,6)进行调用,注意参数的类型必须一致。
可以假设一下不带括号:
int* p();
这相当于一个返回int*型函数的声明。
&test1和test2都可以得到一个函数的地址,可以用
printf("%p\n",test);
printf("%p\n",&test);
进行验证,得到的是两个相同的地址。
函数指针数组
这是一个数组,它存放的是函数指针。我们先来看一下他的书写格式:
void(*p1[5])();
int(*p2[10])(int,int);
我们逐个分析,变量p1先与 [] 结合,表示它是一个数组,然后这个数组里面存储的是 void(*)() 这样类型的函数指针,无返回值无参数。类似于:
int *p1; //这是一个整型指针
int *p1[5]; //刚才上面讲过,这是个数组,里面存储的是int* 类型的指针
void(*p2)(); //这是一个函数指针
void(*p2[5])(); //可以参考p1,它俩都在变量名后面加了[5],改变为数组,存储没加[5]之前代表的类型
函数指针数组在解决需要调用大量相同函数返回值和相同参数个数、类型的时候,有非常重要的作用。
指向函数指针数组的指针
为了加深理解,我们来学习这个指针,我感觉一般不会用到。
这是一个指针,书写格式如下:
void(*(*p)[5])();
int(*(*p)[10])(int,int);
首先括号的优先级高,我们先看最里面的括号,p先与 * 结合表示他是一个指针,从括号里面出来,与 [5] 结合,表示它指向一个数组,剩下 void(*)(),表示数组里面保存的是返回值为void没有参数的函数指针。类似于:
int p1[5]; //这是一个整型数组
int (*p1)[5]; // p先与*结合,表示他是一个指针,括号出来与[]结合,表示他指向一个数组,剩下一个 int 表示这个数组里面存储的是整型
int(*p2[10])(int,int); //上面讲过,这是一个函数指针数组
int(*(*p2)[10])(int,int); //类似于p1的解释。
总结
指针和数组,只要搞清楚优先级,从高到低,一步一步从括号走出来,逻辑不能乱。