注意: 如果第一次接触指针,请点击下面这个链接,看完以后再来看这篇,以防直接劝退。
C语言指针基础
1.返回值是指针的函数
指针函数:
函数的返回值的类型既可以是整型(若没有设定,则默认为整型),字符型,等。当然也可以是指针类型。
返回值为指针类型的函数又称为指针类型的函数
,简称指针函数
。
具体定义格式如下:
类型名 *函数名(参数表)
int *a(int x)
{
printf("这个函数的返回值是指针");
return NULL;//返回值为空指针
}
//解释一下
//这里函数名先和()结合,表示这是一个函数
//然后a()再和前面的*结合,表示这是一个指针类型的函数。
//最后与前面的int结合,表示这是int指针类型的函数,返回值是指针
//(这个过程有点类似前面的指针数组,可以翻上去复习一下)
2.指向函数的指针变量(函数指针)重点
c语言的每个函数的编译的时候,都分配了一段连续的内存空间和一个入口地址,
这个入口地址就称为“指向函数的指针”
,即函数指针
。可以用一个变量来存储函数指针,这个变量就称为
“指向函数的指针变量”
或者函数指针变量。通过
函数指针变量
就可以调用所指向的函数,改变它的值就可以动态调用不同的函数。
2.1 声明函数指针
类型说明符 (*变量名)()
注意:这种形式虽然看着奇怪,看着有点像定义函数,但是
但是,咱就是说但是,告诉自己,这是在声明一个指针,这个指针是函数指针,他还是个指针变量!!!!
举个例子:
int (*foo)();
//说明一下:
//foo先和*结合(括号的运算优先级高),表明该变量名是指针变量
//然后(*foo)后面的括号表示该指针变量指向一个函数
//最前面的int 表明这个函数返回值类型为Int
//这个变量foo是专门用来存放整型函数的入口地址的
- 函数指针变量定义时,并不指向哪一个具体的函数,而是指向空指针。
再举几个函数指针的例子熟悉一下:
int (*ptr1)(double);
//定义一个函数指针ptr1,这个指针指向的函数有如下属性:
//返回值是int
//传入的参数是double
void (*ptr2)(char*);
//定义了一个函数指针ptr2,这个指针指向的函数又如下属性:
//返回值是void(空值,没有返回值)
//传入参数类型是字符指针
来吧,烧脑环节,区分一下下面这几个东西都是啥玩意?
int *ptr1();
int (*pt2)();
int* (*pt3)();
//揭晓答案
int *ptr1();
//这是在声明一个函数,这个函数具有如下属性:
//返回值:int*(int类型的指针)
//函数名:ptr1
//传入参数:无参数
int (*pt2)();
//这是在声明一个函数指针,这个函数指针所指向的函数具有如下属性:
//返回值:int
//传入参数:无
//函数名:肯定不知道呀,值知道指向函数的指针,函数名是不知道的,也不需要知道
int* (*pt3)(int*);
//好家伙,这个buff叠满了
//这是在声明一个函数指针,这个函数指针所指向的函数具有如下属性:
//返回值:int*(int类型的指针)
//传入参数:int*
2.2 使用函数指针
那如何通过函数指针变量调用函数呢?
那就是让函数指针变量p指向一个具体的函数,即将某个函数的入口地址赋值给这个指针变量。
那一般函数的入口地址在哪里呢?
函数名就代表函数的入口地址,是函数指针类型的符号常量。(这里和数组有点类似。)
那赋值给函数指针变量p以后,如何使用p来调用这个函数呢?
因为函数名本身就保存的是这个函数的入口地址,
所以,我们可以将函数名直接赋值给函数指针,
那么现在,这个函数指针就相当于是函数名了。
以前我们怎们用这个函数名调用函数,现在就怎们用这个函数指针调用函数
具体看下面代码示例
int (*ptr1)();
int UsePointFunction()
{
printf("这个函数是用函数指针调用的!");
}
ptr1 = UsePointFunction;//将函数UsePointFunction的值赋值给ptr1
ptr();//通过函数指针调用函数
代码运行结果
为了后面书写方便,我们给函数指针起个别名,类似**int (*ptr1)();**
这样的写法太麻烦了。
那具体怎么操作呢?
typedef int (*Ptr)();
Ptr ptr1;
上面这行代码是啥意思呢?
以后要是想定义返回值为int,传入参数为空的函数指针,直接写ptr就行了。
同理,再举几个例子吧:
typedef void (*Ptr1)(int);
Ptr1 ptr;
//以后在想定义返回值为空,传入参数的函数指针直接写第二行就行了
typedef long (*Ptr2)(double);
Ptr2 ptr;
//以后要定义返回值为long,传入参数为double的函数指针,直接写第六行就行了
2.3 传递函数指针
直接看代码,这就和普通的变量传参是一模一样的,但是效果很神奇。
int add(int num1, int num2)
{
return num1 + num2;
}
int subtract(int num1, int num2)
{
return num1 - num2;
}
typedef int (*fptr)(int ,int);
int comput(fpt opt, int num1, int num2)
{
return opt(num1, num2);
}
//直接将函数名add和subtract当做实参传入,
//则comput就会调用add和subtract
//这的太牛啦!!!
printf("%d\n", comput(add, 1, 2));
printf("%d\n", compute(subtract,5,6));