C語言中交換兩個整數的值之傳值呼叫和傳址呼叫
阿新 • • 發佈:2019-01-06
在C語言中,一說到交換兩個整數的值,大家第一反應可能是這樣的程式碼。定義一個第三方變數來輔助交換。
那有些人可能會說,不定義第三變數,可以啊,我在主函式外部再寫一個Swap交換函式,通過呼叫函式來交換兩個數的值嘛!於是,就有了這樣的程式碼
那麼我們來看一下執行結果
顯然這個函式並沒有達到預期的效果,那麼問題來了,這是為什麼呢?我明明呼叫了這個函式呀,怎麼就沒有交換數值呢?
這個問題我們先放下,我們先來看一下程式執行過程以及數值和記憶體的變化情況
我們可以看到,我們在呼叫交換函式的時候,主函式中定義的兩個整數num1和num2的值的確傳給了函式的引數x和y,但是,num1和num2的地址與x和y的地址是沒有關聯的,這說明num1和num2給Swap函式提供的是當前這兩個變數的值的一份臨時拷貝,當這兩個變數當前的值被函式呼叫的時候,這兩個變數就與函式沒有關係了。 接下來,函式內部的程式一行行執行結束之後 我們可以看到函式內部的x和y的值交換了。 再跳回到主函式進行輸出,這個時候輸出的num1與num2依舊是主函式中被賦給的值,即傳給函式形參的值,而不是通過函式執行之後的值,所以這個程式碼沒有輸出我們預期的結果。
這也就是我們常說的傳值呼叫。
經過修改之後,我們又寫出了這樣得程式碼
我們先來看一下執行結果
毫無疑問,這個結果實現了我們的期望值。我們再來看一下記憶體地址的情況
這裡我們可以看到,num1與num2的地址和x與y的地址相同,也就是說,在呼叫num1和num2這兩個變數的值的時候,我們通過呼叫這兩個變數的地址來引用其地址裡存放的值,這個時候進入到函式內部,把x地址裡的值賦給變數tmp,把y地址裡的值賦給x,再把tmp的值賦給y,也就是說把x地址裡的值放到了y地址裡,把y地址裡的值放到x地址裡,然後返回到主函式中,因為num1與x的地址相同而num2與y的地址相同,所以當x與y的值變了的時候,num1與num2的值也發生了變化,於是輸出結果也就是我們所預期的交換後的值。這就是傳址呼叫。
說到這裡,也許有人又有問題了,你不是說不允許定義第三變數嗎?呼叫的交換函式裡定義的tmp不就是第三變數嘛?
好啦好啦。我的錯啦。這回真的不定義第三變量了。提供兩種方法
第一,加減法運算
num1=num1+num2
num2=num1-num2
num1=num1-num2
第二,異或運算
首先,我來給大家介紹一下異或運算。相異為1,相同為0。比如3和5異或,即 011^101, 011----->3 101----->5 異或之後 110----->6 101 異或之後 011------>3 110 異或之後 101------>5 我們可以發現兩個數與這兩個數異或的結果,這三個數每兩兩異或,結果都是第三個數。於是這個程式碼就寫出來了
如有錯誤,歡迎指出!
#include<stdio.h>
int main()
{
int num1 = 10;
int num2 = 20;
int tmp = 0;
tmp = num1;
num1 = num2;
num2 = tmp;
printf("num1 = %d num2 = %d\n",num1,num2);
return 0;
}
這個執行結果我就不拿出來了,他是符合我們預期結果的。那麼,如果要求,不允許定義第三變數交換兩個整數的值,你會怎麼做呢?那有些人可能會說,不定義第三變數,可以啊,我在主函式外部再寫一個Swap交換函式,通過呼叫函式來交換兩個數的值嘛!於是,就有了這樣的程式碼
#include<stdio.h>
int main()
{
int num1 = 10;
int num2 = 20;
int Swap(int x,int y);
Swap(num1,num2);
printf("num1 = %d num2 = %d\n",num1,num2);
return 0;
}
int Swap(int x,int y)
{
int tmp;
tmp = x;
x = y;
y = tmp;
return 0;
}
那麼我們來看一下執行結果
顯然這個函式並沒有達到預期的效果,那麼問題來了,這是為什麼呢?我明明呼叫了這個函式呀,怎麼就沒有交換數值呢?
這個問題我們先放下,我們先來看一下程式執行過程以及數值和記憶體的變化情況
我們可以看到,我們在呼叫交換函式的時候,主函式中定義的兩個整數num1和num2的值的確傳給了函式的引數x和y,但是,num1和num2的地址與x和y的地址是沒有關聯的,這說明num1和num2給Swap函式提供的是當前這兩個變數的值的一份臨時拷貝,當這兩個變數當前的值被函式呼叫的時候,這兩個變數就與函式沒有關係了。 接下來,函式內部的程式一行行執行結束之後 我們可以看到函式內部的x和y的值交換了。 再跳回到主函式進行輸出,這個時候輸出的num1與num2依舊是主函式中被賦給的值,即傳給函式形參的值,而不是通過函式執行之後的值,所以這個程式碼沒有輸出我們預期的結果。
經過修改之後,我們又寫出了這樣得程式碼
#include<stdio.h>
int main()
{
int num1 = 10;
int num2 = 20;
int Swap(int *x,int *y);
Swap(&num1,&num2);
printf("num1 = %d num2 = %d\n",num1,num2);
return 0;
}
int Swap(int *x,int *y)
{
int tmp = 0;
tmp = *x;
*x = *y;
*y = tmp;
return 0;
}
我們先來看一下執行結果
毫無疑問,這個結果實現了我們的期望值。我們再來看一下記憶體地址的情況
這裡我們可以看到,num1與num2的地址和x與y的地址相同,也就是說,在呼叫num1和num2這兩個變數的值的時候,我們通過呼叫這兩個變數的地址來引用其地址裡存放的值,這個時候進入到函式內部,把x地址裡的值賦給變數tmp,把y地址裡的值賦給x,再把tmp的值賦給y,也就是說把x地址裡的值放到了y地址裡,把y地址裡的值放到x地址裡,然後返回到主函式中,因為num1與x的地址相同而num2與y的地址相同,所以當x與y的值變了的時候,num1與num2的值也發生了變化,於是輸出結果也就是我們所預期的交換後的值。這就是傳址呼叫。
說到這裡,也許有人又有問題了,你不是說不允許定義第三變數嗎?呼叫的交換函式裡定義的tmp不就是第三變數嘛?
好啦好啦。我的錯啦。這回真的不定義第三變量了。提供兩種方法
第一,加減法運算
num1=num1+num2
num2=num1-num2
num1=num1-num2
#include<stdio.h>
int main()
{
int num1 = 35;
int num2 = 20;
num1 = num1+num2;
num2 = num1-num2;
num1 = num1-num2;
printf("num1 = %d num2 = %d\n",num1,num2);
return 0;
}
第二,異或運算
首先,我來給大家介紹一下異或運算。相異為1,相同為0。比如3和5異或,即 011^101, 011----->3 101----->5 異或之後 110----->6 101 異或之後 011------>3 110 異或之後 101------>5 我們可以發現兩個數與這兩個數異或的結果,這三個數每兩兩異或,結果都是第三個數。於是這個程式碼就寫出來了
#include<stdio.h>
int main()
{
int num1 = 10;
int num2 = 20;
num1 = num1^num2;
num2 = num1^num2;
num1 = num1^num2;
printf("num1 = %d num2 = %d\n",num1,num2);
return 0;
}
這兩個程式結果都是正確的。如期的交換了兩個變數的值。如有錯誤,歡迎指出!