跳转表的基础:回调函数

目录

为什么要写这篇

为什么要用回调函数

回调函数的使用

关于空指针void *

完整代码

收集的回调函数的文章


 


为什么要写这篇

因为要写状态机相关的文章,用到的基础知识还是提一下吧。昨天的时候和一个同学的同学聊天,她也是单片机软件方面的工程师,之前觉得她好厉害,听同学说她做过很多东西。昨天聊天的时候问了她一个问题,C程序的,她竟然怀疑这个C#的代码,而且我提示了有个问题是关于强制类型转换的,她竟然不知道强制类型转换,好吧,我后来又问了一下她听说过回调函数吗,她说只见过STM32的HAL库中用到,自己并不清楚具体实现。

说起来如果不是因为编译环境的某种问题,可能我也不会这么经常写可在电脑上运行的C语言程序,如果不是如今公司接触的一些东西,可能我也不知道回调函数是什么东西。莫将容易得,便作等闲看。我过去的实习和第一份工作都没听说过回调函数。

单纯的写C语言程序而不依赖单片机我认为是熟悉C语言很好的方式,因为编写完一键编译运行。对C语言越熟悉对于单片机程序来说编译次数就可减少好多次,因为我们开发用的某个编译环境有某种问题,每次编译都是全部文件编译,快的话两三分钟编译完成,慢的话二三十分钟,和电脑性能有关。而且调试方法就是变量串口打印输出,对于C语言基础不好的我来说,往往一个小功能就得多次编译,变量打印,分析,修改,观察现象来实现,耗时真的苦不堪言。

扯远了,就是说一下认知有前后,了解一些东西很正常,不了解也很正常,时候未到。

为什么要用回调函数

好像是因为软件分层的思想,将程序逻辑和函数实现相分离。

回调函数就是通过函数指针调用的函数。函数指针就是指向函数的指针。

下面是函数指针声明和函数声明的对比,(*Print_Func)表明这是一个指向函数的指针,指向的函数的参数为const void *类型,指向的函数的返回值为void。前面必须有typedef ,表明Print_Func是一个函数指针类型,类似uint8_t、int16_t 。

/* 数据打印函数指针 */
typedef void (*Print_Func)(const void *);

void int16_value_print(const void * value);
void uint32_value_print(const void * value);

回调函数的使用

通过将int16_value_print 或 uint32_value_print 作为函数参数传入,另一个将待操作的数据传入,就能调用对应的函数执行。

void data_output(Print_Func print, const void * value)
{
    print(value);
}

 调用对应函数来完成打印

/* 主函数 */
int main(void)
{
    // int16_t s16_temp_val[10] = {-255, 3442};
    // uint32_t u32_temp_val[2] = {85536, 96275};

    int16_t a = -255;
    uint32_t b = 85536;
    int16_t *s16_temp_val = &a;
    uint32_t *u32_temp_val = &b;

    data_output(uint32_value_print, (void *)u32_temp_val);
    data_output(int16_value_print, (void *)s16_temp_val);

    return 0;
}

关于空指针void *

此处代码配合回调函数使用了空指针。空指针就是不清楚指向的数据类型是什么的指针,常用于数据传递。如果了解指针的使用,那么空指针也就很好理解了。 函数定义时指针类型由 int16_t * 或 uint32_t * 变为 void *, 函数调用时将本来的int16_t * 或 uint32_t * 强制转换为void *类型,当真正处理的时候再强制转换为对应的类型。指针不是要打印的,指针指向的数值是要打印的,因此使用时(而不是定义时,定义时的*表示这是个指针类型)在指针名前加*表示指针指向的数据。

/**
 * int16_value_print
 * @brief 	将数据以int16_t形式打印出来
 * @param	value 用const修改防止被意外篡改
 * @retval 	None
 */
void int16_value_print(const void * value)
{
	printf("\t %d \n", *(int16_t *)(value));
}

/**
 * uint32_value_print
 * @brief 	将数据以uint32_t形式打印出来
 * @param	value 用const修改防止被意外篡改
 * @retval 	None
 */
void uint32_value_print(const void * value)
{
	printf("\t %d \n", *(uint32_t *)(value));
}

完整代码

#include <stdio.h>
#include <stdint.h>

/* 数据打印函数指针 */
typedef void (*Print_Func)(const void *);

void int16_value_print(const void * value);
void uint32_value_print(const void * value);

/**
 * int16_value_print
 * @brief 	将数据以int16_t形式打印出来
 * @param	value 用const修改防止被意外篡改
 * @retval 	None
 */
void int16_value_print(const void * value)
{
	printf("\t %d \n", *(int16_t *)(value));
}

/**
 * uint32_value_print
 * @brief 	将数据以uint32_t形式打印出来
 * @param	value 用const修改防止被意外篡改
 * @retval 	None
 */
void uint32_value_print(const void * value)
{
	printf("\t %d \n", *(uint32_t *)(value));
}


void data_output(Print_Func print, const void * value)
{
    print(value);
}

/* 主函数 */
int main(void)
{
    // int16_t s16_temp_val[10] = {-255, 3442};
    // uint32_t u32_temp_val[2] = {85536, 96275};

    int16_t a = -255;
    uint32_t b = 85536;
    int16_t *s16_temp_val = &a;
    uint32_t *u32_temp_val = &b;

    data_output(uint32_value_print, (void *)u32_temp_val);
    data_output(int16_value_print, (void *)s16_temp_val);

    return 0;
}

收集的回调函数的文章

C语言函数指针之回调函数

C语言、嵌入式重典知识:回调函数

猜你喜欢

转载自blog.csdn.net/quanquanxiaobu/article/details/113981414