指针是学习数据结构的基础,,c语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上。因此,说指针是c语言的灵魂,一点都不为过。
同时数据结构的实现大部分都离不开指针。
最近实现队列本来以为十拿九稳,没想到怎么都调不过。
队列定义
typedef struct Queue
{
struct QueNode * _leader;
struct QueNode * _tail;
}Queue;
节点定义
typedef struct QueNode
{
Quetypedef data;
struct QueNode *_next;
}QueNode;
初始化
void QueueInit(Queue *pq)
{
assert(pq);
pq->_leader=pq->_tail = NULL;
}
插入队列
上面的都能实现,但是到插入就有问题了,这是我开始时候的代码
void PushQueue(Queue *pq,Quetypedef x)
{
if(pq->_leader == NULL)
{
pq->_leader-_data = pq->_tail->_data = x;
}
else
{
pq->_tail->_next = x;
pq->_tail = pq->_tail->_next;
}
}
结果程序总是崩溃,但是我的逻辑上是没有问题的,插入数据到一个队列,如果队列为空则让整个队列的头和尾都为这个值,否则头节点不动,尾节点向后移动。
后来才发现忘记了malloc函数,相当于指针只有看的权限,没有修改的权限,所以程序会崩溃
void PushQueue(Queue *pq,Quetypedef x)
{
if(pq->_leader == NULL)
{
pq->_leader = pq->_tail = BuyNode(x);
}
else
{
pq->_tail->_next = BuyNode(x);//BuyNode(x)功能是分配节点
pq->_tail = pq->_tail->_next;
}
}
分配节点的代码
QueNode *BuyNode(Quetypedef x)
{
QueNode* QNew = (QueNode*)malloc(sizeof(QueNode));
QNew->data = x;
QNew->_next = NULL;
return QNew;
}
然后我在想malloc函数是让指针有权限修改分配的内存,还是让这段内存变成可修改的内存
#include <stdio.h>
#include <malloc.h>
int main()
{
int *a;
a = (int*)malloc(sizeof(int));
*a = 3;
printf("%d",*a);
int *b = a;
printf("%d",*b);
}
程序运行成功,说明malloc函数分配的内存空间是可修改的,而不是让指针有了修改权限
C99中规定malloc用于申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。
除此之外还有一个踩的坑,我开始写的释放节点的代码
free(pq->_leader);
pq->_tail = NULL;
pq->_leader = NULL;
我就想如果释放一个空指针按理来说程序会崩溃,因为free函数是找到指针指向的空间,而对于一个空指针的操作必然会引起程序的崩溃,但是加上后程序运行成功,在查到了C99规定
**C99:将null指针传递给free或者cfree在传统实现中由实现定义其行为。新版本中调用无意义。
**也就是说这段代码没有实际作用
总结:指针可以指向任意地址,但是只能修改malloc分配的有效地址,否则会程序崩溃
free(NULL)不会导致程序崩溃,但是代码本身无意义