C语言 函数指针

  1. 概念
    • 在C语言中,函数指针是一种特殊的指针类型,它指向的是函数而不是普通的数据变量。函数在内存中有其入口地址,函数指针就是用来存储这个地址的变量。
  2. 函数指针的定义
    • 函数指针的定义形式如下:
      • 返回值类型 (*指针变量名)(参数类型列表);
      • 例如,定义一个指向返回值为int,参数为intint的函数的指针:
        int (*funcPtr)(int, int);
        
      • 这里funcPtr就是一个函数指针变量,它可以指向任何返回值为int且有两个int类型参数的函数。
  3. 函数指针的赋值与使用
    • 赋值
      • 可以将一个函数的地址赋给函数指针。例如:
        int add(int a, int b) {
            return a + b;
        }
        
        int main() {
            int (*funcPtr)(int, int) = add;
            // 或者 int (*funcPtr)(int, int); funcPtr = add;
            return 0;
        }
        
    • 使用函数指针调用函数
      • 一旦函数指针被赋值,就可以通过函数指针来调用它所指向的函数。有两种方式:
        • 直接使用函数指针变量调用:
          int add(int a, int b) {
              return a + b;
          }
          
          int main() {
              int (*funcPtr)(int, int) = add;
              int result = funcPtr(3, 5);
              printf("Result: %d\n", result);
              return 0;
          }
          
        • 也可以将函数指针作为函数参数传递,在另一个函数中调用:
          int add(int a, int b) {
              return a + b;
          }
          
          void callFunction(int (*funcPtr)(int, int), int num1, int num2) {
              int result = funcPtr(num1, num2);
              printf("Result: %d\n", result);
          }
          
          int main() {
              callFunction(add, 3, 5);
              return 0;
          }
          
  4. 函数指针数组
    • 可以定义函数指针数组,这在需要根据不同情况调用不同函数时非常有用。例如:
      int add(int a, int b) {
          return a + b;
      }
      
      int subtract(int a, int b) {
          return a - b;
      }
      
      int multiply(int a, int b) {
          return a * b;
      }
      
      int main() {
          int (*funcArray[])(int, int) = {add, subtract, multiply};
          int result = funcArray[1](5, 3);
          printf("Result: %d\n", result);
          return 0;
      }
      
    • 在这个例子中,funcArray是一个函数指针数组,它包含了addsubtractmultiply三个函数的指针。通过funcArray[1]选择subtract函数的指针,然后调用subtract(5, 3)得到结果。
  5. 函数指针作为函数返回值
    • 函数可以返回函数指针。例如:
      int add(int a, int b) {
          return a + b;
      }
      
      int subtract(int a, int b) {
          return a - b;
      }
      
      int (*selectFunction(int choice))(int, int) {
          if (choice == 0) {
              return add;
          } else {
              return subtract;
          }
      }
      
      int main() {
          int (*funcPtr)(int, int);
          funcPtr = selectFunction(1);
          int result = funcPtr(5, 3);
          printf("Result: %d\n", result);
          return 0;
      }
      
    • 在这个例子中,selectFunction函数根据传入的choice参数返回add函数或subtract函数的指针,然后在main函数中使用这个返回的函数指针调用相应的函数。
  6. 用途
    • 回调函数
      • 函数指针常用于实现回调函数机制。例如,在一个排序算法函数中,可以将一个比较函数的指针作为参数传入。这样用户就可以根据自己的需求定义不同的比较函数,实现不同的排序逻辑。
    • 事件驱动编程
      • 在事件驱动的程序中,函数指针可以用来指向不同的事件处理函数。当某个事件发生时,通过函数指针调用相应的处理函数。
    • 实现多态性(类似概念在C语言中的体现)
      • 虽然C语言没有像面向对象语言那样的多态性,但函数指针可以在一定程度上实现类似的功能。例如,通过函数指针数组,可以根据不同的情况调用不同的函数,类似于多态性中的根据对象类型调用不同的方法。

  1. 如何使用函数指针调用函数

    • 直接调用
      • 首先,定义一个函数指针并将其指向一个函数。例如,有一个函数int add(int a, int b),定义函数指针并赋值如下:
        int (*funcPtr)(int, int) = add;
        
      • 然后,可以使用函数指针直接调用函数:
        int result = funcPtr(3, 5);
        
    • 作为函数参数调用
      • 定义一个函数,该函数接受一个函数指针作为参数。例如:
        void callFunction(int (*funcPtr)(int, int), int num1, int num2) {
            int result = funcPtr(num1, num2);
            printf("Result: %d\n", result);
        }
        
      • 在调用这个函数时,将实际的函数名作为参数传入:
        int add(int a, int b) {
            return a + b;
        }
        
        int main() {
            callFunction(add, 3, 5);
            return 0;
        }
        
  2. 如何通过函数指针访问结构体成员(假设函数指针指向的函数操作结构体)

    • 首先定义一个结构体和操作该结构体的函数。例如:
      struct Point {
          int x;
          int y;
      };
      
      int getX(struct Point *p) {
          return p->x;
      }
      
    • 然后定义函数指针并赋值:
      int (*funcPtr)(struct Point *);
      funcPtr = getX;
      
    • 在使用函数指针时,传入结构体指针参数:
      struct Point p = {3, 5};
      int result = funcPtr(&p);
      
    • 这里通过函数指针funcPtr调用getX函数,getX函数通过传入的结构体指针p访问结构体成员x
  3. 函数指针与数组指针的区别

    • 指向的对象不同
      • 函数指针:指向的是函数的入口地址。函数指针的定义形式为返回值类型 (*指针变量名)(参数类型列表),例如int (*funcPtr)(int, int),它指向的是一个接受两个int参数并返回int值的函数。
      • 数组指针:指向的是数组。数组指针的定义形式为数据类型 (*指针变量名)[数组大小],例如int (*arrPtr)[5],它指向的是一个包含5个int元素的数组。
    • 指针运算不同
      • 函数指针:函数指针的指针运算在标准C中没有定义(因为函数在内存中的布局不是像数组那样连续存储元素的形式)。虽然在某些编译器下可能有一些特定的实现,但从标准角度看,不应该对函数指针进行算术运算(如++--等)。
      • 数组指针:数组指针可以进行指针运算。例如,如果arrPtr是一个指向包含5个int元素数组的指针,那么arrPtr + 1将指向内存中紧接着当前数组的下一个包含5个int元素的数组(假设数组在内存中是连续存储的)。
    • 用途不同
      • 函数指针:主要用于实现回调函数、函数表(函数指针数组)等功能,用于在不同的代码模块之间传递函数的调用关系,实现类似于多态的行为。例如,在排序算法中传入比较函数指针,以实现不同的排序逻辑。
      • 数组指针:用于处理多维数组(特别是不规则的多维数组)或者在函数参数传递中传递数组的地址而不丢失数组的维数信息。例如,在处理矩阵运算时,使用数组指针可以方便地遍历矩阵。
posted @ 2024-10-02 22:44  西北野狼  阅读(15)  评论(0编辑  收藏  举报