- 论坛徽章:
- 3
|
本帖最后由 captivated 于 2013-01-12 00:25 编辑
回复 90# cokeboL
不是的.
我函数的第一个参数是 node_t **h, 这表示调用方不需要有头节点,
调用方只需要创建一个头指针即可.
- node_t *list = NULL;
- while (1)
- {
- ...
- list_append(&list, data, size);
- ...
- }
复制代码 就可以了.
如果, list_append的原型是这样子:
int list_append(node_t *h, void *data, int size);
那么显然在list_append函数中无法改变调用方的头指针, 于是必须要调用方预先提供一个头节点才行.
如果, list_append的原型是这样子:
node_t *list_append(node_t *h, void *data, int size);
那么, 如果list_append中调用malloc失败, 你将如何告诉调用方你的函数失败? -- 返回NULL是不好的(因为这样调用方要自己用多一个临时指针来判断调用是否失败).
那么, 我们最终的原型是
int list_append(node_t **h, void *data, int size);
这代表, 在list_append中, 那么第一次插入的数据就是头节点(也即, 用户传入的头指针是NULL).
所以, 在list_append中, 你需要判断 *h 究竟是不是NULL. 那么使用一级指针的做法如下:
- node_t *tmp = *h;
- if (*h == NULL)
- {
- *h = n;
- }
- else
- {
- while (tmp->next != NULL)
- tmp = tmp->next;
- tmp->next = n;
- }
-
复制代码 那么对比一下使用二级指针的做法:- node_t **cur = h;
- while (*cur)
- cur = &(*cur)->next;
- *cur = n;
复制代码 首先, 二级指针的代码简洁了很多. 其次, 二级指针很明显少了一个判断.
其实, 二级指针之于一级指针, 其优势就是在绝大多数情况下, 都能省略掉使用一级指针时那个多余(exceptional)的判断. 当然, 我这个实例的话有些不够说服力, 因为毕竟不循环单链表尾插什么的, 不过是写着玩儿的. 但是, 这个例子毫无疑问确实地体现了二级指针之于一级指针的真正优点所在[如果在系统性能至关重要并且频繁调用的地方, 这个省去的判断是很重要的, 它能提高CPU分支预测的命中率].
|
|