在使用C語言時,由於函數的高度獨立性,即在函數結束時會釋放先前使用的局部變量,直接采用賦值的方式,有時無法達到利用函數處理數值的目的,這時合理利用指針,可以幫助我們越過函數高度獨立性的“大山”。
下面這段代碼要求用戶輸入兩個整數,並將兩數交換順序輸出:
#include<stdio.h>
void ichange(int*one,int*another);
void ichange(int*one,int*another){
int num;
num = *one; //將one所指向空間值復制一份給num空間
*one = *another;
*another = num;
}
int main(){
int num1;
int num2;
printf("請輸入兩個整數:");
scanf("%d%d",&num1,&num2);
ichange(&num1,&num2);
printf("%d %d",num1,num2);
return 0;
}
我們可以利用圖形來具體了解計算機處理這段代碼的大致過程:
a.
圖a展示了計算機調用函數時,內存堆棧空間內存放數據的大致模型。
1.函數運行過程
1.1首先調用main函數,申請了兩個int型變量num1,num2,由於先int num1,所以num1先入棧
1.2接着賦值,假設用戶輸入為7 25,則通過scanf中的&(取地址符)直接給先前申請的num1,num2變量賦值,由此可知變量實質就是一段首地址及長度已知的內存空間!
1.3.1
接着main函數順序運行至調用ichange函數,在開始處理子函數前,計算機會先將主函數處理的進度保存起來,以便於稍后繼續執行,而儲存的進度信息會以指針變量的形式存入棧中,方便索引。
在這之后計算機才開始申請ichange函數中定義的空間,由於編譯的特點,計算機總是從右至左的讀取我們書寫的代碼,所以我們可以看到是*another空間先被申請,接着是*one空間,最后是函數主體中的num空間。(需要注意的是:函數申請的局部變量的空間,隨着函數開始而被申請,隨函數結束而被釋放)。
b.
圖b表示了ichange函數進行運算時,堆棧空間內變量的變化情況。
由於函數實參部分傳遞的是num1和num2的地址,所以在子函數內部修改參數值時,通過地址傳遞,num1和num2空間的值也立刻得到了修改,所以最終即使ichange函數運行完畢局部變量空間釋放,也達到了我們修改num1,num2值的目的。
2.關於棧指針。
實際上,計算機通過棧指針控制了棧空間的分配。棧擁有棧底指針和棧頂指針,棧頂至棧底中的信息為有用信息。一般情況下棧底指針不變,通過修改棧頂指針值,擴大或縮小棧頂至棧底的數據量,以達到數據的增加和刪除。(棧頂指針上移,寫入數據;棧頂指針下移,刪除數據)。所以函數申請空間過程,實質是堆棧棧頂指針上移過程,而函數運行完畢釋放空間過程則是棧頂指針下移過程。
3.如有意見建議歡迎討論!