/*
读书笔记类型多种多样,有摘抄型的,有感想型的,有批注型的,有摘要型的……
现在正在研读《C和指针》,其中有很多我认为必要的知识点,摘抄并简单整理了一下,记录在这里。
*/
50. 链表(linked list)是一些包含数据的独立数据结构(通常称为节点)的集合。链表中的每个节点通过链或指针连接在一起,程序通过指针访问链表中的节点。通常节点是动态分配的。
51. 单链表是一种使用指针来存储值的数据结构。链表中的每个节点包含一个link字段,用于指向链表的下一个节点。另外,有一个独立的根指针指向链表的第1个节点。由于节点在创建时有采用动态分配内存的方式,所以它们可能分布于内存之中。但是,遍历链表是根据指针进行的,所以节点的物理排列无关紧要。单链表只能以一个方向进行遍历。
52. 无序单链表插入新值,可以插到任何位置。把一个新节点链接到链表中需要两个步骤:
1)新节点的link字段必须设置为指向它的后续节点;
2)前一个节点的link字段必须设置为指向这个新节点。程序设计中,可以通过保存一个指向必须进行修改的link字段的指针,而不是保存一个指向前一个节点的指针,来解决在链表起始位置插入新值的特殊情况。
53. 双链表中的每个节点包含两个link字段,一个指向链表的下一个节点,另一个指向链表的前一个节点。双链表有两个根指针,分别指向第1个节点和最后一个节点。因此,遍历双链表可以从任何一端开始,而且在遍历过程中可以改变方向。为了把一个新节点插入到双链表中,必须修改4个指针。新节点的前向和后向link字段必须被设置,前一个节点的后向link字段和后一个节点的前向link字段也必须进行修改。
/*
链表这一部分在学生时代就被老师一笔带过了,印象中就是一串用指针串起来的结构体。今天研读《C和指针》,12章讲的就是链表,章标题就是《使用结构和指针》。到目前为止,实际的工作中还没有用到链表这么“复杂”的数据结构,在这里只是摘抄些自认为有价值的东西吧。
*/
54. 一些高级声明:
1) int *f( void );
这个比较简单,f是一个函数,返回值类型是一个指向整型的指针。
2) int (*f) ( void );
f是一个函数指针,它所指向的函数返回值类型是一个整型值。
3) int *(*f) ( void );
f是一个函数指针,它所指向的函数返回值是一个整型指针,只有对其进行间接访问,才能得到一个整型值。
4) int *f[ ];
这个也比较简单,f是一个数组,它的元素类型是指向整型的指针(指针数组)。
5) int (*f[ ]) ( void );
f是一个数组,数组元素的类型是函数指针,它所指向的函数返回值是整型值。
6)int *(*f[ ]) ( void );
f是一个数组,数组元素的类型是函数指针,它所指向的函数返回值是指向整型的指针。
55. 函数名被使用时总是由编译器把它转换成函数指针。
56. 用户把一个函数指针作为参数传递给其他函数,后者将“回调”用户的函数,这种技巧称为“回调函数”。如果编写的函数能够在不同的时刻执行不同类型的工作或执行只能由函数调用者定义的工作,都可以使用这个技巧。
57. 函数指针最常见的两个用途是转换表(jump table)和作为参数传递给另一个函数(回调函数)。
58. 转移表由一个函数指针数组组成(这些函数必须具有相同的原型),函数通过下标选择某个指针再通过指针调用对应函数。
/*
现在再回头去看我之前的一篇博文《TI蓝牙BLE 协议栈代码学习——OSAL(下)》,OSAL中进行任务处理的数组const pTaskEventHandlerFn tasksArr[ ]就是一个转换表,转换表里面保存的就是处理各任务的函数名,而这些函数名会被编译器转换成函数指针。使用转换表要特别注意的是,不要越界,这跟数组的使用一样,但是转换表一旦访问越界了,造成的后果可能会更恶劣。
转换表在书中是通过一个例子来讲述的,大家可以到书中去详细了解。
*/
用户872456 2014-10-14 22:59
用户1776833 2014-10-14 10:57
//deleted
用户967031 2014-10-11 13:47