实验环境:MacOS + VSCode
一、准备工作
1.下载VSCode,并安装如下插件
2.解压老师给的安装压缩包,并用VSCode打开
二、运行代码
1.
gcc -g menu.c linktable.c -o test
编译程序,发现缺少string.h头文件,引入后编译成功
2.运行发现help,version命令可以正常运行,quit不能正常运行。
3.
echo "set startup-with-shell off" >> ~/.gdbinit
sudo gdb ./test
mac系统这里有坑,如果不能因为sig不能正常运行需要在命令行输入第一句,然后必须用sudo运行gdb。
4.用命令行能进入的gdb可以run,用VSCode的命令行进入的gdb无法run,我们选择用命令行运行。
5.观察代码发现p是空指针输出"This is a wrong cmd!\n ",说明我们此时获得的p是空指针
6.p是FindCmd函数的返回值,观察FindCmd函数。
7.findCmd调用了SearchLinkTableNode函数,观察。
从中我们观察到返回NULL共有三个条件,具体如下:
a. pLinkTable == NULL 不会出现该种情况
b. Conditon == NULL 也不会出现该种情况
c. pNode == pLinkTable->pTail 唯一出现NULL的可能
8.这里有一个int Condition(tLinkTableNode* pNode),这是一个callback函数,SearchLinkTableNode是call-in方式函数,一个函数作为参数,这个函数就是callback函数。
9.链表中前两个节点可以遍历到,最后一个节点遍历不到,根据InitMenuData函数,观察AddLinkTableNode函数。
10.容易观察出这个链表是采用尾插法创建的,pNode != pLinkTable->pTail这个条件无法遍历到最后一个节点,改成pNode != NULL即可。
11.重新编译,运行成功。(代码较为简单,阅读完成了debug,但是创建好了gdb的环境)
三、callback函数解析
1.回调函数:就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。一般情况下,应用程序会时常通过API调用库里预先准备好的函数,有些库函数需要应用先传递给它一个函数,好在合适的时候来调用。这个被传入的、又被调用的函数就是回调函数。这里必须清楚一点:函数b是你以参数形式传给函数a的,那么函数b就叫回调函数。
2.回调函数的优点:
(1)使得程序设计更加灵活。
(2)当我们想通过一个统一接口实现不同内容的时候,用回调函数来实现就非常合适。
(3)任何时候,如果你所编写的函数必须能够在不同的时刻执行不同的类型的工作或者执行只能由函数调用者定义的工作,你都可以用回调函数来实现。
(4)使用此函数可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
参考博客: