小祥在學習李春葆的數據結構教程時發現一個小問題,建立順序表和輸出線性表,這兩個函數的形參是不一樣的。
代碼在這里↓↓↓
1 //定義順序表L的結構體 2 typedef struct 3 { 4 Elemtype data[MaxSize]; 5 int length; 6 }SqList; 7 8 //建立順序表 9 void CreateList(SqList * &L,ElemType a[ ],int n) 10 { 11 int i; 12 L = (SqList * )malloc(sizeof(SqList)); 13 for(i = 0 ; i < n ; i++) 14 L->data[i] = a[i]; 15 L->length = n; 16 } 17 //輸出線性表: 18 void DispList(SqList *L) 19 { 20 int i; 21 for(i = 0; i < L ->length; i++) 22 printf(“%d”,L->data[i]); 23 printf(“\n”); 24 }
思考這個形參為什么要寫成這兩種形式,即SqList *L和SqList * &L的區別。
*L是指針,全稱是指針變量,是一個用來保存內存地址的變量。在這里是一個指向順序表,存儲順序表的地址的變量。
* &L是指針類型的引用,引用(reference)是c++對c語言的重要擴充。引用就是原變量的另外一個名稱(別名),引用變量本身沒有自己的實際存儲空間,對引用變量的操作,就是在操作原變量。這里的* &L代表原指針。
這兩個有着一個共同點,都指向順序表 L ,如果在函數中修改L 的內容,都影響到 L 的內容。
不同點則是,在函數中修改指針本身所指向的地址,*L 不會發生改變,而* &L會發生改變。
首先,* &L是引用類型的指針,代表的是原指針,我們在函數中對指針的操作,都是直接對原指針的操作,無論是指針的內容,還是指針指向的地址,都會發生改變。
那么,*L為什么在函數中會改變不了所指向的地址呢?
其實,這里我們要延伸到函數形式參數和實際參數的很基礎,也很重要的知識點了。
形參出現在函數定義中,在整個函數體內都可以使用。實參出現在主調函數中,進入被調函數后,實參也不能使用。在函數調用的時候,主函數把實參的值傳送給被調函數的形參,從而實現數據的傳送。
但是,在這個函數調用的過程中,數據傳送是單向的,即數據只能由實參傳到形參,而形參不會傳回實參。也就是說,我們在函數中改變形參的值,實參的值是不會發生改變的,這就是函數調用中的單向值傳遞。
那么,回到我們的 *L 來,*L其實就是一個變量,在這里是一個形式參數。形式參數在函數中其實是對實參的拷貝,也就是說,函數中形參其實是另一個變量,一個復制原變量的新變量,有不同於原變量的內存空間,存在於函數中,函數調用結束,即刻釋放內存空間。
也就是說,我們在函數中改變 *L 所指向的地址,不是在對原變量進行改變,而是對原變量的一個復制體進行改變,改變了復制體,卻沒有改變本體。
所以,在函數中 *L 不能改變所指向的地址。
好了,這就是小祥在學習數據結構的過程中遇到的問題,一開始在網上搜索一下,發現能夠解釋的不多,也是有點混亂,同時也是自己的基礎知識有點混亂,所以打算寫下這篇博客來梳理自己的知識,如果寫的有不對的地方,歡迎大家指出來,我會繼續改進。謝謝大家。
附加:
嚴蔚敏的《數據結構(C語言版)》中形參是 &L ,而李春葆的《數據結構教程》是 *&L,兩者是不同的。
