26 函数与指针分析

1 函数类型

  • C 语言中的函数有自己特定的类型

  • 函数的类型由返回值,参数类型和参数个数共同决定

    如:int add(int i,int j) 的类型为 int(int,int)

  • C 语言中通过 typedef 为函数类型重命名typedef type name(parameter list)

    如:typedef int f(int,int);typedef void p(int);

2 函数指针

  • 可以通过函数类型定义函数指针

    • 函数指针用于指向一个函数
    • 函数名是执行函数体的入口地址(类似于数组名代表数组首元素的地址)
    • 语法:FuncType* pointer;
  • 也可以直接定义:type(*pointer)(parameter list);

    • pointer函数指针变量名
    • type :所指函数的返回值类型
    • parameter list :所指函数的参数类型列表
  • 示例:函数指针的使用

    • Demo

      #include <stdio.h>
      
      typedef int(FUNC)(int);
      
      int test(int i)
      {
          return i * i;
      }
      
      void f()
      {
          printf("Call f()...
      ");
      }
      
      int main()
      {
          FUNC* pt = test;  //通过函数类型定义函数指针,并用test函数名进行初始化(函数名代表函数体的入口地址)
          void(*pf)() = &f;  //直接定义函数指针,并用函数f的地址初始化(&f也是函数体的入口地址,与f相同)
          
          printf("pf = %p
      ", pf);
          printf("f = %p
      ", f);
          printf("&f = %p
      ", &f);
          
          pf();//调用函数
          
          (*pf)();//调用函数
          
          printf("Function pointer call: %d
      ", pt(2));
          
          return 0;
      }
      
    • 编译运行

      pf = 0x8048400
      f = 0x8048400
      &f = 0x8048400
      Call f() ...
      Call f() ...
      Function pointer call : 4
      
  • 问题:如何使用 C 语言直接跳转某个固定的地址开始执行?

    • 利用函数指针,如对于上面的代码修改为: void(*pf)() = 0x8048400; ,直接利用函数指针跳转到地址 0x8048400 执行,而这个地址恰好是函数 f 的地址

3 回调函数

  • 回调函数是利用函数指针实现的一种调用机制

  • 回调机制原理

    • 调用者不知道具体事件发生时需要调用的具体函数
    • 被调函数不知道何时被调用,只知道需要完成的任务
    • 当具体事件发生时,调用者通过函数指针调用具体函数
  • 回调机制中的调用者和被调用者互不依赖 ---> 监听者模式

  • 示例:回调函数使用

    • Demo

      #include <stdio.h>
      
      typedef int(*Weapon)(int);
      
      //对于fight函数,只知道使用某种武器进行攻击,而不知道是何种武器
      void fight(Weapon wp, int arg)
      {
          int result = 0;
          
          printf("Fight boss!
      ");
          
          result = wp(arg);
          
          printf("Boss loss: %d
      ", result);
      }
      
      //对于具体的武器的函数来说,并不知道什么时候会被调用
      int knife(int n)
      {
          int ret = 0;
          int i = 0;
          
          for(i=0; i<n; i++)
          {
              printf("Knife attack: %d
      ", 1);
              ret++;
          }
          
          return ret;
      }
      
      int sword(int n)
      {
          int ret = 0;
          int i = 0;
          
          for(i=0; i<n; i++)
          {
              printf("Sword attack: %d
      ", 5);
              ret += 5;
          }
          
          return ret;
      }
      
      int gun(int n)
      {
          int ret = 0;
          int i = 0;
          
          for(i=0; i<n; i++)
          {
              printf("Gun attack: %d
      ", 10);
              ret += 10;
          }
          
          return ret;
      }
      
      int main()
      {
          //在main函数中,通过函数指针连接fight函数与knife,sword,gun函数,实现回调
          fight(knife, 3);
          fight(sword, 4);
          fight(gun, 5);
          
          return 0;
      }
      
    • 编译运行

      Fight boss!
      Knife attack: 1
      Knife attack: 1
      Knife attack: 1
      Boss loss : 3
      
      Fight boss!
      Sword attack: 5
      Sword attack: 5
      Sword attack: 5
      Sword attack: 5
      Boss loss : 20
      
      Fight boss!
      Gun attack: 10
      Gun attack: 10
      Gun attack: 10
      Gun attack: 10
      Gun attack: 10
      Boss loss : 50
      
原文地址:https://www.cnblogs.com/bky-hbq/p/13773683.html