C/C++ 指针和函数

C/C++ 指针和函数

函数指针是 C 语言里一项很重要的特性,C/C++ 程序员必须掌握。它提供了一种灵活操作函数的方式,让我们能在运行时动态决定到底执行哪个函数。

1. 函数名理解

函数名本身就可以看成一个指向函数的指针。当你用到函数名时,它会自动转成指向函数入口地址的指针。也就是说,我们可以通过指针间接调用函数。看下面的示例:

#include <stdio.h>

void demo()
{
   printf("hello demo\n");
}

int main() {

    // 1. 直接调用函数
    demo();

    // 2. 函数名为指向函数入口地址的指针
    printf("%ld\n", demo);

    // 3. 间接调用函数
    void(*func)() = demo;
    (*func)();

    return 0;
}

程序运行结果:

hello demo
4363710224
hello demo

2. 函数指针类型

函数指针类型该怎么定义呢?看下面的示例:

#include <stdio.h>

int demo(int a, int b)
{
    return a + b;
}

int main() {

    // 1. 第一种方式
    int(*func1)(int, int) = demo;
    int result = func1(10, 20);
    printf("result = %d\n", result);

    // 2. 第二种方式
    typedef int(FUNC_TYPE)(int, int);
    FUNC_TYPE* func2 = demo;
    result = func2(10, 20);
    printf("result = %d\n", result);

    // 3. 第三种方式
    typedef int(FUNC_POINTER)(int, int);
    FUNC_POINTER* func3 = demo;
    result = func3(10, 20);
    printf("result = %d\n", result);

    return 0;
}

程序运行结果:

result = 30
result = 30
result = 30

3. 函数指针数组

函数指针数组,顾名思义就是数组里每个元素都是函数指针类型。它提供了一种动态选择和调用函数的机制,适合需要按不同条件选不同函数去执行的场景。在命令调度、事件处理、状态机、算法实现和插件化架构里都用得很多。

#include <stdio.h>


void demo1(int a, int b)
{
    printf("demo1 a + b = %d\n", a + b);
}

void demo2(int a, int b)
{
    printf("demo2 a + b = %d\n", a + b);
}


void demo3(int a, int b)
{
    printf("demo3 a + b = %d\n", a + b);
}

int main() {

    void(*func_array[])(int, int) = {demo1, demo2, demo3};

    // 调用数组中的函数
    func_array[1](10, 20);
    func_array[0](30, 40);
    func_array[2](50, 60);

    return 0;
}

程序运行结果:

demo2 a + b = 30
demo1 a + b = 70
demo3 a + b = 110

4. 回调函数

回调函数是一种编程模式,它把一个函数的指针当参数传给另一个函数,等特定事件或条件发生时,再通过这个函数指针反过来调用对应的操作。回调是实现事件驱动和异步编程的一种灵活手段。

回调这个模式里,有两个主要角色:

  1. 调用方:某个函数或模块,它要做一些操作,并在合适的时候调用回调函数。
  2. 回调函数:由调用方提供的一个函数,规定了特定事件发生时该干什么。它的指针被传给调用方,到了合适的时机由调用方来调用。

示例代码:

#include <stdio.h>



int do_logic(int(*func)(int, int))
{
    int a = 20;
    int b = 10;

    int result = func(a, b);

    return result;
}

int my_func1(int a, int b)
{
    return a + b;
}

int my_func2(int a, int b)
{
    return a - b;
}

int main() {

    // 函数名做函数参数
    int result = do_logic(my_func1);
    printf("result = %d\n", result);

    result = do_logic(my_func2);
    printf("result = %d\n", result);

    return 0;
}

程序执行结果:

result = 30
result = 10

5. 指针作返回值

函数指针还能当函数的返回值,这在某些场景下非常有用。比如你可以写一个函数,根据传入的参数返回不同的函数指针,这样就能按不同条件选不同的函数去执行,让程序逻辑更动态。

#include <stdio.h>
#include <string.h>


int my_func1(int a, int b)
{
    return a + b;
}

int my_func2(int a, int b)
{
    return a - b;
}


typedef int(*FUNC_POINTER)(int, int);
FUNC_POINTER do_logic(const char *type)
{
    if (0 == strcmp(type, "plus"))
    {
        return my_func1;
    }
    else if(0 == strcmp(type, "minus"))
    {
        return my_func2;
    }

    return NULL;
}

int main() {

    // 函数名做函数参数
    int result = do_logic("plus")(10, 20);
    printf("result = %d\n", result);

    result = do_logic("minus")(10, 20);
    printf("result = %d\n", result);

    return 0;
}

程序运行结果:

result = 30
result = -10