首先,指针是什么呢?
我们看这样一段代码
#include<stdio.h> int main() { int a = 10;//在内存中开辟一块空间 int *p = &a;//取出变量a的地址,用&操作符 //将a的地址存放在p变量中,p就是一个指针变量 return 0; }
知道了这些以后,让我们再来看几个有关指针的定义。
指针数组
指针数组是数组,是一个存放指针的数组。
举个栗子:
int *arr1[10];//*表示每个数组元素是一级指针,int表示指针指示的类型是整型 char *arr2[4];//*表示每个数组元素是一级指针,char表示指针指示的类型是字符型 char **arr3[5];//**表示每个数组元素是二级指针,char表示指针指示的类型是字符型数组指针
数组指针是指针,是指向数组的指针。
举个栗子:
int (*p)[10];//p先和*结合,说明p是一个指针变量,然后指针指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫指针数组。
//需要注意的是,[ ]的优先级要高于 * 号的,所以必须加上 ()来保证p先和*结合。
既然已经了解了数组指针和指针数组之后我们来看看下面这些表达式表示的是什么意思。
int arr[5]; int *parr1[10]; int (*parr2)[10]; int (*parr3[10])[5];//这里我就只解释一下parr3
首先,parr3和[10]结合,表明parr3是一个数组,是一个有10个元素的数组。
然后,我们把 parr3[10] 删去,得到 int (*) [5] ,那么这个就是该数组每个元素的类型,显然,这是数组指针。
而这个数组指针,指向的一个有5个元素的数组。
所以,这是一个存放10个数组指针的数组,每个数组指针指向一个有5个元素的数组。
接下来再看函数指针
函数指针,顾名思义,就是指向函数的指针。
举个栗子:
void test() { printf("I love China"); } int main() { void (*pfun1)();//函数指针 }//pfun1先和*结合,说明pfun1是指针,指向的是一个函数,指向的函数无参数,返回值类型为void。
那么
来看两段代码:
//代码1 (*(void(*)())0)(); //代码2 void (*signal(int,void(*)(int)))(int);
有点复杂,你可以多思考一会儿。
以下是我个人的解释,仅供参考。
//代码1
把0强制类型转换为函数指针(存着函数地址),*得到函数,就是在调用函数,该函数参数类型为空,返回类型为void。
//代码2
signal是一个函数的声明,signal有2个参数,一个是int ,一个是 void(*)(int),即函数指针,
该函数指针指向的函数,有一个int参数,返回类型为void。
我们把该函数删去后得到 void (*)(int),即一个函数指针,同时它也是该函数的返回类型。
即signal函数的返回类型为一个函数指针,该函数指针指向的函数,有一个int参数,返回类型为void。
你明白了么?
当然 代码2 过于复杂,所以我们可以稍微简化一下,比较容易理解。
如下:
typedef void(*pfun_t)(int);//类型重定义,将函数指针重定义为 pfun_t pfun_t signal(int,pfun_t);//还原并简化代码那么其实还有 函数指针数组
函数指针数组是一个数组,数组中的每个元素的类型是函数指针。
举个栗子:
int (*parr1[10])();//parr1先和 [ ] 结合,说明 parr1是数组,将该数组名删去,得到 int (*)( ) ,显然,这是一个函数指针,所以该数组的每个元素都是一个 int (*)( )类型的函数指针。
你理解了么?
接下来最复杂的来了。
指向函数指针数组的指针
一步步看下来的话,你应该也可以解释清楚。
对的,指向函数指针数组的指针,首先,它是一个指针,该指针呢,指向一个数组,而数组的每个元素都是函数指针。
举个栗子吧:
void test(const char* str) { printf("%s\n",str); } int main() { void (*pfun)(const char*) = test;//函数指针pfun void (*pfunArr[5])(const char*); pfunArr[0] = test;//函数指针的数组pfunArr void (*(*ppfunArr)[10])(const char*) = &pfunArr;//指向函数指针数组pfunArr的指针ppfunArr return 0; }你看明白了么?
稍微有一点复杂,慢慢理解,多思考,就明白了。