函数指针和指针函数的讲解

文章目录

  • 指针函数
  • 函数指针
  • 函数指针的定义与指针函数的声明的区别
    • 函数指针的定义
    • 指针函数的声明
  • typedef在函数指针方面的使用
    • typedef和using 给函数指针的类型取别名
    • typedef和using 给函数的类型取别名

指针函数

指针函数:
也叫指针型函数,本质上就是一个函数,是一种特殊的函数类型,它返回一个指针作为函数的返回值。
指针型函数声明的格式:
返回类型* 函数名(参数列表);
或者
返回类型 *函数名(参数列表);
推荐使用第一种声明方式。更清晰明了
其中,返回类型是指针类型,函数名是指针型函数的名称,参数列表是指针函数的参数列表。

例如:
普通函数(即返回值不是地址)

int fun0(int);//声明了一个返回值类型为int,函数参数为int型的函数。

指针函数(即返回值是地址)

int* fun1 (int);//声明了一个返回值为整型的指针,函数参数为int,int的指针型函数。
void* fun2 (int, int);//声明了一个返回值为void型的指针,函数参数为int,int的指针型函数。

注意: 指针函数一定有返回值,形如 void* 的返回值类型,为任意指针类型。而不是无返回值。不管返回的是 int* 还是 void* 建议都判断是否为空指针。

例子:

int* func(int a, int b);//指针型函数声明; 或者为 int* func(int, int);即声明里的形参可以只写类型,不写形参变量。这也是推荐的写法。
	
int* func(int a, int b) //指针型函数的定义
{
   int* p = (int*)malloc(sizeof(int));//在堆内存中申请了一块4个字节的内存,并把指向这块堆内存的地址返回,赋值给指针变量p
   *p = a + b;//将a+b的和,赋值给指针变量p所指向的内存空间。注:当*p作为左值时,表示的就是它所指向的那块内存对应的变量。
   return p;
}

注意:和普通函数一样,指针函数没有形参时,声明时后面的括号()也是不能省略的,否则就变成 指针变量的定义了。

指针函数就是一个普通的函数,普通到仅仅是因为它的函数返回值是地址值而已。这与其他一般函数唯一的区别
就是在函数名前面多了一个*号,而这个函数就是一个指针函数。
一句话总结:返回的是地址值,在指针函数被调用时用指针变量来接收此指针函数返回的地址值。

函数指针

函数指针是指向函数的指针变量,即本质是一个指针变量。因此“函数指针”本身首先应是指针变量。
只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。C/C++在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。

先看一个int类型的指针的声明,然后和函数型指针做对比:

int* p;

声明一个函数型(假如是一个有两个int类型的参数以及一个 int类型的返回值)的指针:

int (*fun_ptr) (int, int);//定义 一个【有两个int类型的参数以及一个int类型的返回值】类型 的函数指针。fun_ptr 就是指针变量名

故此指针可以用来指向:符合 一个有两个int类型的参数以及一个 int类型的返回值的任意函数。
在这里插入图片描述二者不同的只是 函数指针多了一个参数列表
例子:

#include 
#include 

void Fun(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <

函数指针的定义与指针函数的声明的区别

函数指针的定义

void (*fun) (int, int);//fun 是一个有两个int类型的参数以及一个 int类型的返回值的函数指针。//指针就是变量。变量名是fun.

注意:这里提指针和地址的区别,指针是变量,它是用来存储地址 ,而地址是一个常量值。类似于,变量和变量的值之间的关系。

指针函数的声明

void* fun (int, int);//fun是返回一个指针的函数

注意: 定义函数指针时,第一个()是不能省略的,如果省略的话,就会导致完全不同的情况了。就变成 指针函数的声明了。

typedef在函数指针方面的使用

typedef 操作符是在C/C++中经常使用的。它不仅可以给简单类型 取别名。还可以给复杂类型 取别名。
格式如下:
typedef 类型 别名;
在C++11 中又引入了using的另一个作用 来给类型 取别名。using这个作用和typedef的作用是一样的,二者等价,在某些复杂类型上使用有using 比用typedef更容易直观理解。
格式如下:
using 别名 = 类型;
注意:using之前已有的作用是 引入命名空间 如引入标准库的命名空间: using namespace std;

typedef和using 给函数指针的类型取别名

typedef 在给 函数指针类型 取别名上的应用(这也是typedef 在给复杂类型 取别名上的应用):

typedef void (*FUN) (int, int);//这里的FUN是一种 void (*) (int, int) 类型的别名,而不是上面的函数指针,而是一个类型。可以FUN来表示 函数指针 的类型。

注意: 也许这样 写 typedef void (*) (int, int) FUN; 更符合 “typedef 类型 别名;”的格式。但是这样写会编译报错,也就是这种写法是错误的。
也可以用using 来取别名(C++11中开始支持)

	using FUN = void (*) (int, int);//感觉这样方式更符合理解。这也是为啥C++11中开始支持使用using来给类型取别名的意义。

注意:不管 typedef 还是using 都是给已有的简单类型 或者 复杂类型 取一个别名,而不是创建一个新的类型。

例子:

#include 
#include 

typedef void (*FUNC) (int, int);//使用typedef来取别名
using FUNC1 = void (*) (int, int);//使用using来取别名
using FUNC2 = int (*) (int, int);//使用using来取别名

void Fun(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <

typedef和using 给函数的类型取别名

也可以给函数类型取别名

typedef void FUNC4(int, int);//使用typedef来给函数的类型取别名,不看 前面的typedef 单独看 void FUNC4(int, int);是一个函数声明,即函数原型。

和函数指针取别名进行比较:

typedef void (*FUNC) (int, int);//使用typedef来给函数指针的类型取别名
分析:
//void (*FUNC) (int, int); //定义一个 返回值为void,拥有两个int参数类型的 函数指针,函数指针名称为FUNC
//void FUNC4(int, int); //声明一个 返回值为void,拥有两个int参数类型的 函数,此函数的函数名是 FUNC4.
//它们就是一个表示 函数指针,一个表示函数
//同理 形如上面的 两者前面都加上typedef后,FUNC表示的函数指针的类型别名。 FUNC4表示的函数的类型的别名。

完整代码演示:

#include 
#include 

typedef void (*FUNC) (int, int);//使用typedef来给函数指针的类型取别名
typedef void FUNC4(int, int);//使用typedef来给函数的类型取别名,不看 前面的typedef 单独看 void FUNC4(int, int);是一个函数声明,即函数原型。
//或者使用using
//using FUNC = void (*) (int,int); //等号右侧表示函数指针的类型
//using FUNC4 = void (int,int); //等号右侧表示函数的类型
//两个类型的区别就是一个有*,一个没有*


//void (*FUNC) (int, int); //定义一个 返回值为void,拥有两个int参数类型的 函数指针,函数指针名称为FUNC
//void FUNC4(int, int); //声明一个 返回值为void,拥有两个int参数类型的 函数,此函数的函数名是 FUNC4.
//它们就是一个表示 函数指针,一个表示函数
//同理 两者前面都加上typedef后,FUNC表示的函数指针的类型别名。 FUNC4表示的函数类型的别名。

void Fun(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <

你可能感兴趣的:(C,and,C++的笔记,c++,开发语言)