資料結構學習筆記之C指標基礎

2021-06-21 22:53:24 字數 3116 閱讀 7012

之所以稱為c指標基礎,因為這些關於指標的操作是基礎,但是我們又經常出錯,在做資料結構的實驗時,又遇到不少,我在這裡做下總結,希望能幫到大家。另:這個不像之前的演算法,也可能仍會有很多認識不足的地方,希望大家指正!

變數的位址即指標,儲存位址值的記憶體單元稱為指標單元。指標的型別由其型別決定,基型別是指指標變數所指的資料型別。所以指向整型變數的指標我們稱之為整型指標;指向字元變數的指標稱為字元指標等等

一、下面說一點最最基本的

1.指標宣告:int *p, *q;  //整型指標

char *ch;  //字元指標

void *n;    //這個指標也是對的,可以指向任何資料,要規定長度,這個到高階的時候再說吧

2.指標使用:a.取位址單目運算子:int sum, *psum; psum = ∑即取sum的位址作為指標psum

b.指標的賦值:上面的psum = ∑ 是乙個賦值語句;同樣型別的指標 p = q; 這樣賦值也是對的

c.間訪單目運算子 * :sum = *q; 就可以將q所指單元的值賦給sum。

3.針對結構體指標,訪問資料項的操作,方式有兩種:

a. p->name  (如果p是雙重指標,則應該為 (*p)->name )

b. (*p).name

ps:假設p是指向乙個結構的指標,該結構內部有乙個名為name的資料項,對它的訪問可以使用上面兩種方式

這裡就有乙個必須要理解的問題,指標的所指,賦值操作p = q;他們的指標單元是不一樣的,儲存單元的位址是不一樣的,所以有時候在一些鍊錶操作中,會犯這個錯誤,雖然你認真考慮了,但是你會認為

q = s;

p =q; 那麼 p 的指向就變成了s, 這個本身是沒有太大問題,但是如果你要修改的是p指標的儲存單元,那就絕對錯了!下面給出例子說明。

二、指標操作常見錯誤

引用我自己寫的基於鍊錶的順序表的插入操作。

下面是鍊錶的頭結點和資料項結構定義:

typedef int status;

typedef structhnode;

typedef struct lnodelnode;

下面是listinsert函式實現**:

status listinsert(hnode *l, int i, lnode *e)

if((n = (lnode *)malloc(sizeof(lnode))) == null)

exit(-1);

//gets(n->name);

scanf("%s",n->name);

scanf("%d",&(n->age));

scanf("%s",n->phone);

scanf("%s",n->mail);

printf("錄入完成!\n");

if(i>1)

n->next=p->next;

p->next=n;

}else

不等價於 l->firstnode=n;

}++(l->length);

(*e) = (*n);

return ok;

}//listinsert

第乙個容易犯的錯誤:如上面**的34、35行,和注釋寫的一樣,前面我有將l->firstnode(鍊錶的首元結點)賦值給p,是賦值,不是連儲存單元也改了,我們的目的是修改l的首元結點,很顯然要修改其指標單元,所以如果在這裡你寫的是p = n, 就百分百錯了!(你這樣做編譯器是不會報錯的!某種程度上說,指標的風險性就在於這裡,它很靈活)

第二個容易犯的錯誤:就是我們在引數列表中定義了乙個指向資料元素的結構指標,我們用它返回我們前面插入的資料元素,那麼如何返回?

錯誤寫法: e = n;

錯誤好像還不是很明顯哈,很多人就會問,為什麼在函式體內可以用e指標訪問所指的結構體,返回到主函式就不行了(我覺得這和彙編裡面的子程式呼叫差不多,傳的是指標,我們明顯會對它進行壓棧保護,也就是說在子函式e改變了指向,指向n所指的結構(某塊儲存空間),但是返回時,e所指的結構體(另一塊儲存空間)恢復了)。那麼當然就沒有預期效果了。

正確的寫法:如上面**的38行 (*e) = (*n); 這是兩個同型別的結構體直接賦值,你也可以乙個個的資料項賦值,但是明顯那麼做不明智。

關於結構體的賦值,也會有很多的小細節,一併說一下,因為這些細節有時候也很容易被忽略:

第三個容易犯的錯誤:就像前面的(*e) = (*n), e在主函式裡定義,如果你只是定義了,沒有分配儲存空間給它,如果懸掛了,那麼顯然,前面這個語句就是錯誤的,因為e懸掛,沒有所指,沒有實體儲存單元,就會出錯!

另外就是前面說的結構體賦值的兩種方式,一定要清楚等式兩端的資料型別;如果結構體定義了字串,用->來訪問資料項或者賦值會更加麻煩且容易出錯!

小結:前面三個錯誤可簡述為:1.對指標所指位址和本身的儲存位址理解不透徹;2.對指標引數傳值理解不透徹;3.對指標賦值混淆,不清楚資料型別。所以大家要多練習,加深理解就好啦!

此外,再新增一點,定義在不同的標頭檔案下的結構體,在main函式下include後,是可以引用另乙個結構宣告變數的,可以構成巢狀的結構:

//-------二叉樹的二叉鍊錶儲存表示-------

typedef struct bitnode

bitnode, *bintree;

以上是在usr_bintree.h的二叉樹節點定義,下面是usr_stack.h的堆疊資料元素節點定義:

//堆疊的鏈棧表示--棧結點

typedef struct snode

snode;

//堆疊的鏈棧表示--棧元素

typedef struct

sqstack;

在上面在棧結點我就採用了另乙個標頭檔案的二叉樹定義來定義了乙個資料項: struct bitree  *pbtnode; 這樣是沒有任何問題的,實際可行,這是我的實驗,通過測試的!

c 資料結構學習筆記

c 資料結構學習筆記 1 關於類的建構函式 在建構函式前加上explict關鍵字 就可以使建構函式只可以顯式呼叫,而不可以隱式呼叫。下面的例子說明的很清楚 classtest1 普通建構函式 private int num classtest2 explicit 顯式 建構函式 private in...

資料結構學習筆記一 基礎

資料的邏輯結構稱為資料結構 資料結構分為兩類 線性結構 非線性結構 資料的儲存結構分為四種方法 順序儲存方法 該方法主要用於線性的資料結構,非線性的資料結構也可以通過某種線性化的方法來實現順序儲存。索引儲存方法 該方法在儲存節點資訊的同時,還建立附加的索引表。索引表中的每一項稱為索引項,索引項的一般...

資料結構學習筆記一 基礎

資料的邏輯結構稱為資料結構 資料結構分為兩類 線性結構 非線性結構 資料的儲存結構分為四種方法 順序儲存方法 該方法主要用於線性的資料結構,非線性的資料結構也可以通過某種線性化的方法來實現順序儲存。索引儲存方法 該方法在儲存節點資訊的同時,還建立附加的索引表。索引表中的每一項稱為索引項,索引項的一般...