在指针的学习过程中有这么几种指针在定义是经常会让我们犯错:函数指针、函数指针数组、函数指针数组的指针。下面我们逐个了解这几种指针。
一、 函数指针
函数指针顾名思义:指向函数的指针。
我们知道整型、浮点型、字符型指针存放的都是其对应变量的存储地址,那么很容易可以理解,函数指针存放的就是函数的地址。
函数的地址是什么呢? 我们看下面的代码:
void test()
{
printf("hello world\n");
}
int main()
{
printf("%p\n",&test);
printf("%p\n",test);
return 0;
}
可以看出函数名和函数的地址是一样的。那么函数的地址要保存起来势必需要一个指向该函数的指针,也就是我们说的函数指针。
那么问题来了,函数指针怎么定义呢?
看下面的代码:
void test()
{
printf("hehe\n");
}
//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void *pfun2();
首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针?
答案是:
pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。pfun2是在函数指针定义过程中最常见的错误定义的方式。
看下面两段有趣的代码:
//代码1
(*(void (*)())0)(); //这是一个函数调用,将0强转成函数指针,对其解引用得到0地址处的函数。这个函数无参数和返回值类型。
//代码2 void (*signal(int , void(*)(int)))(int); //这是一个函数的声明。该函数的返回值为void (*) (int) ,函数名是signal ,参数有两个,一个是 int,一个是 void (*) (int).
代码2可以化简如下:
typedef void (*func) (int)
func signal(int ,func);
二、函数指针数组
数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组, 比如:
int* a[10]; //定义一个指针数组 每个元素是int*
那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
1.既然是指针 那么变量名必定应该与 [] 先结合构成一个数组 如 :arr[]。
2.这是一个 “函数指针” 数组,整型数组每个元素的类型是整型,那么函数指针数组每个元素的类型就是“函数指针”即 数据类型 + (*) (参数列表)。
然后我们看下面的代码:
int (*parr1[10]])();
int *parr2[10]();
int (*)() parr3[10];
上面几种定义的方法那个是正确的?
答案是:parr1 parr1 先和 [] 结合,说明parr1是数组,数组的内容是什么呢? 是 int (*)() 类型的函数指针。
三、指向函数指针数组的指针
指向函数指针数组的指针是一个 :“指针” 指针指向一个 数组 ,数组的元素都是 函数指针 。
如何定义?
void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = test;
//函数指针的数组pfunArr
void (*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函数指针数组pfunArr的指针ppfunArr
void (*(*ppfunArr)[10])(const char*) = &pfunArr;
return 0;
}
以上就是三种函数的正确理解与定义。