对于函数指针和typedef的结合运用

  实质:函数指针实质是一个指针,并不是函数,函数有自己的函数体,而指针只是一个变量

  指针函数和函数指针的区别:

     指针函数: 实质:是一个函数,有自己的函数体

           格式:数据类型关键字 *xxx(形参)

              {

                  函数体;

              }

     函数指针: 实质:是一个指针,一个变量,常用来调用函数

           格式:数据类型关键字 *指针名)(形参)

 

  功能:指向函数的指针可用于调用它所指向的函数。可以不需要使用解引用操作符,而直接通过指针调用此函数。

  示例1:

      typedef void FUN (char , int);

      void (*pf)(char, int);//声明一个函数指针pf,指向一个返回值为0带有(char,int)两个形参的函数

      FUN fun; //实际就是声明一个void fun(char,int)的函数

      pf=fun;

  两种调用方法如下:

      (*pf)('c',90); // 显式调用

      pf('c',90); // 隐式调用

  示例 2:通过指针调用函数

1. #include <stdio.h>2.3.
2. // 声明一个函数指针,指向的函数形参带有一个char类型,一个int类型,返回类型为 void
3. void (*pf)(char, int);
5. // 声明一个函数,形参为一个 char 类型,一个 int 类型,返回类型为 void
6. void fun(char ,int);
7. int main()
8. {
9.     pf=fun; //函数指针 pf 赋值为 fun 函数的地址(函数名代表函数的地址)
10.    (*pf)('c',90); //调用 pf 指向的函数
11.    pf('a',80);
12. }
13. void fun(char a,int b)
14. {
15.    printf("the argument is %c and %d\n",a,b);
16. }

  运行结果: the argument is c and 90

       the argument is a and 80

  返回指向函数的指针
  函数可以返回指向函数的指针,但是,正确写出这种返回类型相当不容易,例如:
     int (*ff(int))(int*,int);
  要理解函数指针声明的最佳方法是从声明的名字开始由里而外理解。要理解该声明的含义,首先观察“ff(int)”
  是将 ff 声明为一个函数,它带领有一个 int 型的形参。该函数返回“int (*)(int*,int)”它是一个指向函数的指针,所指向的函数返回 int 型并带有两个分别为 int *型和 int 型的形参。
  使用 typedef 可使该定义更简明易懂:
    typedef int (*PF)(int *,int);
    PF ff(int);
  示例:  

#include <iostream>
using namespace std;
typedef void (*callback)(int x);            // 定义一个函数指针类型
void myFunc1(int x)                         // myFunc1 的声明要与callback一样
{
    cout << "This is myFunc1 " << x << endl;
}
void myFunc2(int x)
{
    cout << "This is myFunc2 " << x << endl;
}
void callMyFunc(callback cb, int x)      // 把函数指针类型当做调用函数参数类型
{
    cb(x);
}
int main()
{
    callMyFunc(myFunc1, 1);
    callMyFunc(myFunc2, 2);
    return 0;

}

 下面举几个typedef和函数指针结合使用的例子:

    

 

  左边第一个运行出错 右边两个正确

  出错原因:

  typedef定义的pf是一种void (*)(int)的函数指针类型,pf定义的是指针(它是一个数据类型关键字,类似于int)。

  用pf去声明fun肯定会出错,pf fun,是定义fun为一个函数指针变量(可以理解为函数名),而不是声明函数,右边两个是正确的。

  函数名是可以作为函数指针变量,作为函数的入口地址,但是函数名不仅仅是这种作用。

  函数名相当于表示函数的入口地址,我们调用时通过函数名,让程序跳转到对应函数处开始执行

  

  还可这样使用:

  void (*signal(int signum,void(* handler)(int)))(int); 等价于下面两行

  typedef void (*sighandler_t)(int);

  sighandler_t  signal(int signum,sighandler_t handler)

   

  运行结果: fdsfsfsf1
        fdsfsfsf3

   

  解剖一下signal函数,理解函数指针和typedef

void (*signal(int signum,void(* handler)(int)))(int); 等价于下面两行
typedef void (*sighandler_t)(int);
sighandler_t  signal(int signum,sighandler_t handler)

  分析:先分析第一行,看到这一串的函数声明,不要慌,从内而外一点一点分析:

     1. signal(int signum,void(* handler)(int))这是一个函数,函数名为signal

       (1) 第一个形参:int signum,是一个整形变量;

       (2) 第二个形参:void(*handler)(int),这是一个函数指针,指向:返回值为void型,且带一个int型的形参的函数。

          也就是说,这个形参,是一个指针,或者说是一个地址,可以理解为这个形参是函数名,因为函数名是函数的入口

         地址。里面分析完了。

     2. signal函数的外面是 void(*)(int),想一想,在定义或者声明函数的时候,都需要说明函数返回值的类型,这个signal

       函数的形参已经明确了,但是返回值还不知道,这个void(*)(int)就是返回值类型,这个类型是一个函数指针,碰巧的是,

       这个函数指针指向的函数类型和signal的第二个形参指向的类型相同,都是指向:返回值为空,且带一个int类型形参的函数。

      3. 因此先用typedef定义一种数据类型,这个类型就是void(*)(int),将这种类型定义为,或者说是起名别,叫做sighandler_t

       sighandler_t = void(*)(int),所以可以将void(*)(int)类型的函数,在声明或者定义的时候用sighandler_t。

     4. signal函数返回值为void(*)(int)型,用sighandler_t代替,第2个形参是void(*)(int)型,用sighandler_t代替。

 

 

posted on 2019-03-07 19:11  梦*飞  阅读(4915)  评论(1编辑  收藏  举报