先看一個大家都熟悉的單鏈表結構體
typedef struct node{
int data;
struct node * next;
} PNode,*LinkList;
// 簡化后就是
struct node{
int data;
struct node * next;
};
typedef struct node PNode;
typedef struct node *Linklist;
對于LinkList L: L是指向定義的node結構體的指針,可以用->運算符來訪問結構體成員,即L->data,而(L)就是個node型的結構體了,可以用點運算符訪問該結構體成員,即(L).data**;
對于LinkList L:L是指向定義的Node結構體指針的指針,所以(L)是指向Node結構體的指針,可以用->運算符來訪問結構體成員,即(L)->data,當然,(**L)
就是node*型結構體了,所以可以用點運算符來訪問結構體成員,即(**L).data
;
在鏈表操作中,我們常常要用鏈表變量作物函數的參數,這時,用LinkList L還是LinkList L 就很值得考慮深究了,一個用不好,函數就會出現邏輯錯誤,其準則是:
如果函數會改變指針L的值,而你希望函數結束調用后保存L的值,那你就要用LinkList L,這樣,向函數傳遞的就是指針的地址,結束調用后,自然就可以去改變指針的值;
而如果函數只會修改指針所指向的內容,而不會更改指針的值,那么用LinkList L就行了;
下面說個具體實例吧!
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct Node{
ElemType elem;
struct Node * next;
}Node, * LinkList;
//初始化鏈表,函數調用完畢后,L會指向一個空的鏈表,即會改變指針的值,所以要用*L
void InitList(LinkList *L) {
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;
}
//清空鏈表L,使L重新變為空鏈表,函數調用完后不會改變指針L的值,只會改變指針L所指向的內容(即L->next的值)
void ClearList(LinkList L){ LinkList p; while(p = L->next) free(p);}
//銷毀鏈表L,釋放鏈表L申請的內存,使L的值重新變為NULL,所以會改變L的值,得用*L
void DestroyList(LinkList *L)
{
LinkList p;
while(p = (*L)->next )
free(p);
free(*L);
*L = NULL;
}
void main()
{
LinkList L = NULL;
InitList(&L);
ClearList(L);
DestroyList(&L);
}