指針是學習數據結構的基礎,,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)不會導致程序崩潰,但是代碼本身無意義