左左右学堂 · 课程目录

第26期 一节课讲明白c语言指针(中④)

观看B站原视频 · 文稿与高清画面

hello,小伙伴们,大家好。这里是左左右。这期视频接着给大家讲C语言基础中指针这一部分。在函数那期视频我们写过这样一个Get_R的函数。前面我们讲过给数组名取地址得到的是数组指针。

那么,如果我们给函数名取地址是不是也可以得到函数的指针呢?通过代码来验证一下。点击运行。这时就将函数指针的地址打印出来了。那么,我们应该如何定义一个函数指针呢?也就是要用一个什么样的容器来存放函数指针呢?我们将之前定义好的函数复制下来,将函数名Get_R改为括号*p,将传参过来的变量名去掉。

这里我们就将函数指针定义好了。这时的变量p就是指向函数Get_R的指针。同时,函数名取地址和函数名是等效的,调试输出来看一下,是不是输出结果一模一样?那么,函数指针该怎么使用呢?

视频画面 01:33.5
视频画面 01:33.5 · 1080P 原图 · 查看对应视频

首先,将函数指针解引用得到函数本身,接着将需要的参数传进来。打印输出是不是没有问题?其实,指针函数前的*在c语言中是允许被省略的。打印输出是不是也没有问题?按照这样的逻辑,给结构体名取地址是不是得到的就是结构体指针?我们通过代码来验证一下。

视频画面 02:27.8
视频画面 02:27.8 · 1080P 原图 · 查看对应视频

首先,我们定义一个结构体变量并通过大括号的形式给结构体成员赋值。接着,打印输出。就将结构体指针的地址打印出来了。接着,要用一个什么样的容器来存放结构体指针呢?它和int等基础数据类型指针的定义类似。前面放的是结构体名。

那么,如何通过结构体指针来给结构体成员赋值呢?这里我们要用结构体指针加减号,大于号,加结构体成员名的形式。减号和大于号组成一个箭头,代表指针指向结构体成员。这时打印输出看一下结果,是不是和我们想的一模一样?通过这里我们可以得出这样一个结论。通过结构体名访问或修改结构体成员要用“.”的形式,而通过结构体指针访问或修改结构体成员要用“->”的形式。

这里假设我们有这样一种需求:通过只调用一个函数实现打印输出“hello vscode”或“hello stm32cubeide”或“hello 左左右”。也就是说hello是不变的,后面的内容是可变的。按我们之前学过的内容,我们只能这样写。这时只能输出一种结果,也就是hello后面的内容是不受控的。

这时我们将前面的一个函数拆分为两个。那么,我们该如何将这两个函数关联起来呢?我们刚才讲的函数指针就派上用场了。这时我们将Print_vs这个函数以函数指针的形式传参到Print_h中。再在Print_h中以函数指针的形式来调用Print_vs这个函数。接着,我们在main函数中将Print_vs以函数指针的形式传参到Print_h中。

视频画面 06:05.1
视频画面 06:05.1 · 1080P 原图 · 查看对应视频

点击运行,是不是输出没有问题?这段代码我们还可以简化一下。前面我们说过函数名和函数名取地址等效。我们将这里的取地址符可以去掉。我们可以用typedef。用一个简单的名称来替代这里的函数指针,也就是说这时的函数指针和CallbackFunc等效。接着,我们将这里的函数指针改为CallbackFunc。

同时,前面我们说过函数指针前的*是可以省略掉的。所以,这里我们可以写成这样。点击运行,是不是输出没有问题?接着,我们将剩下几个回调函数也照猫画虎的写一下。点击运行,这时我们是不是就可以随心所欲的输出我们想要的结果了?

那么,回调函数有什么作用呢?如果是我们自己写的回调函数,是不是可以通过不同的回调函数,实现不同的功能。如果我们调用别人的回调函数我们不用考虑Print_h里这一部分有多么复杂,现实中hal库源码中这一部分写的也是十分复杂。我这样简单的写是为了大家能够理解回调函数的实现原理。

视频画面 07:53.7
视频画面 07:53.7 · 1080P 原图 · 查看对应视频

我们在调用时,不用考虑这部分有多么复杂。我们只需要重写回调函数这一部分就可以了。这就是回调函数的现实意义。我们将之前stm3cubeide中写好的代码再拿出来看一下。当时我们使用这个函数HAL_UART_Receive_IT时,只需与知道他是usart中断接收数据的一个函数。

具体他是怎么接收的过程我们不需要知道?我们只需要重写HAL_UART_RxCpltCallback这个回调函数来实现我们想要的功能就可以了。好的,今天的视频就到这里了。您的关注,点赞和收藏是我持续更新下去的最大动力。我们下期见。