点击 <C 语言编程核心突破> 快速C语言入门
指针与指针的指针,我就不信你脑壳不疼
- 前言
- 一、从一个链表实现说起
- 二、指针, 指针的指针, 头疼的来源
- 总结
前言
C实现一个链表,为什么有时候传入指针,有时候传入指针的指针,究竟有什么区别? 今天就简单说说,让你头疼的指针套指针问题。
一、从一个链表实现说起
先看一个简单的链表结构:
我们有一个节点LNode
, 包含一个数据data
, 一个节点指针next
, 将节点指针的类型取名为LinkList
, 所以LinkList
本身就是一个指针.
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode
{
int data;
struct LNode *next;
} LNode;
typedef LNode *LinkList;
我们实现一个链表的生成函数CreateList
, 它的参数是LinkList
的指针, 也就是LNode
节点的指针的指针.
函数会让你输入节点个数,以及每个节点的数值, 形成一个链表,
int CreateList(LinkList *list)
{
LNode *node = NULL;
int cnt;
scanf("%d", &cnt);
for (int i = 0; i < cnt; i++)
{
node = (LinkList)malloc(sizeof(LNode));
if (!node)
{
return 1;
}
scanf("%d", &node->data);
node->next = *list;
*list = node;
}
return 0;
}
比如我们输入 3 0 1 2,
代表链表有3个值, 其值分别是 0, 1, 2.
而如果从头节点算起, 它的储值顺序是反过来的,
是 2, 1, 0 这个顺序, 头节点永远得到最后一次输入的值.
这就是输入指针的指针的目的,
我要改变传入参数的那个节点指针的值,
单单传入节点指针, 将无法做到, 因为C语言没有引用,
需要通过指针解引用来引用那个需要改变的指针.
最后是链表的删除, 我还是传入指针的指针,
链表删除的时候我们是从头节点删除,
一个一个直至节点指向NULL
.
并且保证, 最后传入函数的 list
指向 NULL
.
如果传入的是LinkList
, 则删除链表后list
就是一个野指针, 需要格外注意.
int DeleteList(LinkList *list)
{
LinkList temp = NULL;
while (*list)
{
temp = (*list)->next;
free(*list);
*list = temp;
}
return 0;
}
如果弄懂以上操作, 你可以比较轻松的实现一个栈结构, 后进先出.
下面是个简单的测试用例, 可以通过断点调试, 一步步看看究竟发生了什么.
int main()
{
LinkList list = NULL;
CreateList(&list);
DeleteList(&list);
return 0;
}
二、指针, 指针的指针, 头疼的来源
从上面的例子, 你应该可以基本了解, 在什么时候, 需要操作指针的指针,
本来一级指针理解起来就不是太容易, 二级指针可以说就比较晦涩了,
但有的时候, 你不理解二级指针, 可能无法满足一些需求, 同时, 也可能导致野指针的出现,
对于C这种没有gc
垃圾回收机制, 也没有C++这种RAII
资源管理机制的语言, 谨慎处理指针和内存, 还是挺费头发的.
总结
以上就是在C语言中, 我们运用二级指针作为形参, 实现链表功能的一个简单阐述, 对于C语言, 指针是永远绕不开的话题, 把它玩儿明白, 你就入门了.
点击 <C 语言编程核心突破> 快速C语言入门