旁白
最近小漁夫在看嚴蔚敏、李冬梅《資料結構 c語言版》(第2版),學到第二章順序表的實作時,看到函式引數一會是SqList &L、一會又是SqList L、一會ElemType &e、一會又ElemType e,當場大寫的黑人問號加感嘆號,這都什么玩意,一會有&一會又沒有,都代表什么意思呢?
于是帶著這些問號去找答案,上網上看了很多,看到的比較零散,于是我整理了一下,理清原因后,心想估計也有同學跟我一樣的黑人問號,于是就有著這篇文章,希望能有點幫助吧,
先說答案
嚴書里的代碼是偽代碼,什么是偽代碼?顧名思義不是真的代碼,拿到電腦上去跑不起來的代碼,偽代碼重點是表達思路、表達想法的,
所以,書里函式引數中有&,想表達的意思是:希望通過函式改變該引數的值,可以看到書里在新建順序表、插入一個資料、洗掉資料等改變順序表的操作時用到了SqList &L,因為這些操作會改變表的內容;在查找操作時,沒有改變表,順序表前沒有&,用到了SqList L;在取值時用到了ElemType &e,是想把取到的值通過引數回傳,
在C語言里只能通過指標實作,書里寫的是偽代碼,而不是真正的C代碼;在C++里可以通過指標和參考(C語言無參考)實作,
有些同學可能不太理解怎么通過函式改變傳進來引數的值,下面詳細介紹一個例子就明白了,
詳細介紹
例子是用c語言的指標實作的,說起指標不得不提兩個符號*與&,那先來看指標中的*與&,
C語言指標中的*與&
首先,一般看一個變數,看它的3點,變數名稱、資料、地址,如定義一個變數int a = 5,變數名是a,值是5,在記憶體中的地址是0x00001111,

了解了變數,就可以了解指標了,指標可以理解成記憶體里的地址,指標變數就是存盤地址的變數,
&是取地址運算子,用于取變數地址;例如:int a = 5, &a表示變數a的地址0x00001111,
*出現在不同的地方含義不同,但就我現在理解的,一般出現在兩個地方:
- 函式引數中和變數定義中,表示定義一個指標變數,如
int *p ,int *p = &a. - 等號右邊,
*(地址)表示取值運算,如int a = 5; int *p = &a; *p,中變數啊的值為5,指標變數p的值為0x00001111,*p的值為5,
例子:交換兩變數的值
了解了指標后,來看下這個例子,例子中寫了兩個函式,來交換兩變數的值,第一個函式swap1沒用指標,第二個函式swap2用了指標,結果你猜,哪個函式能改變傳進來引數的值?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int num1 = 1;
int num2 = 2;
swap1(num1, num2);
printf("num1 = %d, num2 = %d\n", num1, num2);
swap2(&num1, &num2);
printf("num1 = %d, num2 = %d\n", num1, num2);
// test();
return 0;
}
void swap1(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
void swap2(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
如圖:運行一下,得到結果,第二個函式起作用了,也就是用了指標的函式能改變傳進來引數的值,實作交換兩變數的效果,這就是通過函式改變傳進來引數的值,

到這里,已經得到答案了,
至于,為什么第一個函式沒有實作交換,有興趣的再往下看看,
單步除錯一下,我發現了其中的奧妙,
除錯開始,如下圖,變數num1值為1,地址為0x62fe1c,變數num2值為2,地址為0x62fe18,

往下走,開始呼叫函式,進到函式swap1里,如圖,變數num1和num2沒什么變化,引數a和b已經接收到傳進來的引數了,同時發現num1、num2的 地址和a、b不一樣,原來函式會把形式引數當作區域變數,然后在堆疊中開辟記憶體空間,用于存放由主調函式傳遞進來的實參值,從而形成了實參的一個副本(替身),

再往下走,走完發現了驚喜,與上圖相比a和b互換了,而變數num1和num2和還是沒什么變化,

最后,函式swap1執行結束,輸出結果num1 = 1, num2 = 2,可以發現雖然變數交換了,但是只是交換了副本(替身),至于為什么用了指標就可以交換真身呢?感興趣,動動小手去探索探索吧,哈哈哈,

附錄
1. *p和**p的區別
int *p 是一級指標,存放的是一個變數的地址,
int **p是二級指標,存放的是指標變數的地址,
例子:
//定義整形變數
int a = 6;
//定義一個指標指向這個變數
int *p = &a;
//定義一個二級指標指向p指標
int **pp = &p;
// 那么取出6的方式都有哪些呢?
printf("a=%d", a);
printf("a=%d", *p);
printf("a=%d", **pp);
以上3行輸出的值都是6 ,
2. *&p和&*p的區別
根據單目運算子運算的優先級,*&p 等價于*(&p),&*p 等價于&(*p),
-
如果
p是指標變數,那么*&p = p,&*p = p,都等于p,但還沒定義p指向哪,存的是誰的地址, -
如果
p是一個int變數,那么*&p = p;而&*p是非法的,因為*p非法,
比如int p =10;那么*&p = *(&p) = p = 10(即從p的地址取值),而&*p = &(*p) 則非法,因為p=10,*10是取記憶體地址為10的值,這在c語言中是不合法的,
后續
我在學習中發現,c只能通過指標實作這種方式,而C++不僅能通過指標實作,還能通過參考實作,并且C++還提倡使用參考,本來想繼續寫寫,什么是C++參考,為什么C++引進這個概念,這個概念有什么好處、C++指標引數和參考引數有什么區別的,但發現跟主題好像離得有點遠,扯到C++去了,作罷,看看后面有機會用C++實作演算法的時候再行補上,
才疏學淺,如有不當,請批評指正,
你的支持也是我的動力,最后筆記對你有用,別忘了點贊支持下哦,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/280892.html
標籤:其他
上一篇:如何通過SSH將TortoiseGit小烏龜關聯GitLab
下一篇:編碼編成翔的十八般兵器
