1. 程式人生 > 其它 >為什麼我的交換函式不起作用?

為什麼我的交換函式不起作用?

技術標籤:c語言指標

文章目錄


前言

不少學習c語言的小白在寫交換函式時都會碰到這樣一個問題:明明在函式裡已經進行了數值交換,但是輸出的值並沒有改變,還是之前的值。這是為什麼呢?讓我們一起來分析一下吧。


一、錯誤示範

我們初學者會想當然的用形參進行數值交換的操作,下面是演示程式碼:

void Swap1(int x, int y)
{
	int tmp = 0;
	tmp = x;
	x = y;
	y = tmp;
}
int main()
{
	int a = 10;
	int b = 20;
	printf("交換前:     a=%d  b=%d\n"
, a, b); Swap1(a, b); printf("Swap1交換後:a=%d b=%d\n", a, b); return 0; }

輸出結果:
在這裡插入圖片描述
我們發現,a和b的值並沒有進行交換,為什麼呢?函式裡明明已經進行交換了呀?這樣做的朋友就是對函式引數的傳遞理解還不夠透徹,我們首先來理解一下函式的實參和形參。

1.實參

真實傳給函式的引數,叫實參。實參可以是:常量、變數、表示式、函式等。無論實參是何種型別的量,在進行函式呼叫時,它們都必須有確定的值,以便把這些值傳送給形參。

2.形參

形式引數是指函式名後括號中的變數,因為形式引數只有在函式被呼叫的過程中才例項化(分配記憶體單元),所以叫形式引數。形式引數當函式呼叫完成之後就自動銷燬了。因此形式引數只在函式中有效。

    int a = 10;
	int b = 20;
	Swap1(a, b);

這裡的a和b是確定的值,叫做實參,把他們傳遞給函式進行下一步操作。

void Swap1(int x, int y)

這裡的x和y就是形參,用於接收 Swap1(a, b) 傳遞過來的引數,然後進行相應的處理,但是處理完以後變數就會自動銷燬。這跟區域性變數類似,只在區域性的範圍內起作用,用完就銷燬了。而 Swap1函式返回值型別是void,沒有返回任何值,所以最終的輸出還是原來的a和b的值,沒有發生任何改變。

也可這麼理解,形參只是實參的一份拷貝,它們都有自己的獨立空間,函式內部只是對拷貝的引數進行操作而不會影響到實參的數值。下圖是除錯狀態下的監視視窗,我們可以看到兩點重要的資訊:

  1. 分別查看了a,b和x,y的地址,它們並不相同,所以x,y的改變並不影響a,b。
  2. 當程式走出函式體時,x,y都變成了灰色,表示已經被銷燬了,這也印證了我們之前所說的結論。

在這裡插入圖片描述

二、正確示範

分析出了錯誤原因,接下來既然好辦了。我們要找到a和b的地址,然後再改變其對應的值,這樣才能達到真正的交換目的。以下是正確的程式碼:

void Swap2(int* px, int* py)
{
	int tmp = 0;
	tmp = *px;
	*px = *py;
	*py = tmp;
}
int main()
{
	int a = 10;
	int b = 20;
	printf("交換前:       a=%d  b=%d\n", a, b);
	Swap1(a, b);
	/*printf("Swap1交換後:a=%d  b=%d\n", a, b);*/
	Swap2(&a, &b);
	printf("Swap2交換後:  a=%d  b=%d\n", a, b);
	return 0;
}

輸出結果:
在這裡插入圖片描述

這裡涉及到了指標的用法,所謂指標就是地址的一個標記,舉個通俗的例子。你去上課的時候,首先要找到教室在哪,你才能上課,而為了方便找到教室,每間教室都會進行相應的編號,如E405就表示E樓的4層第5間教室,有了這個編號你就可以找到教室,找到教室以後,你可以對教室裡的佈局進行改變,例如你可以改變教室裡的桌子數量。同樣道理,在程式裡你可以通過地址找到a和b,然後可以改變其對應的值。

除錯程式後,我們發現a,b的地址和px,py的地址一模一樣,說明函式已經定位到了a和b的空間,接下來只需要對相應的值進行交換,程式就能正確輸出了。


三、總結

我們來進行總結,通過一個小小的交換函式,我們用到了很多知識,首先是函式的呼叫,涉及到實參和形參的使用,如果不理解清楚,很容易會出現邏輯上的錯誤。其次我們還學會用指標進行傳參,這樣就能真正的改變參量的值。所以學習還真不能只看到表面現象,理解到其背後的意義也是很重要的。