延續上一篇的指標,補充 pass by value 和 pass by reference 的差別。
當我們在程式中呼叫函數時,變數的傳遞方式有兩種:pass by value 和 pass by reference。這兩者的區別主要在於傳遞的是「值」還是「記憶體位置的參考」。
這個情況在交換數值的時候會特別明顯。
當變數是以值傳遞時,函數接收到的只是該變數的「複製品/副本」,而非原始的變數。換句話說,在函數中對這個變數的操作,不會影響到主程式(main()
)中原本的變數。
舉例來說,如果遇到 x 和 y 交換的情況但其實是複製地址,不是複製值。
假設我要交換 x 和 y 的值。我的直覺是,設定一個暫時的參數,並讓他們交換。
#include <stdio.h>
#include <cs50.h>
void swap (int a, int b);
int main(void)
{
int x = 1;
int y = 2;
printf("x is %i, y is %i\n",x,y);
swap(x,y);
printf("x is %i, y is %i\n",x,y);
}
void swap (int a, int b)
{
int tmp = a; //a先丟掉tmp裡面
a = b; //此時a的位置是空的,再把b丟進去
b = tmp; // b的位置變空了,再把a從tmp撈回來
}
但出來的結果卻沒有交換,為什麼呢?
因為實際在記憶體的寫在 main 裡面的 function 跟 main 外的 function 存的方式不太同個平面。
所以 swap中的 x 和 y 並非等於 main。而只是他的「副本」(copy)。
這時候只是pass by value。
那這樣怎麼解決呢?
參考傳遞則完全不同,它傳遞的是變數的「記憶體位置」。因此,函數可以直接操作原變數,而不只是操作一個副本。這樣的傳遞方式在需要修改變數內容時特別有用。
讓他指向值,指向 a 和 b 代表的地址,所以程式碼就要改成:
#include <stdio.h>
#include <cs50.h>
void swap (int *a, int *b);
int main(void)
{
int x = 1;
int y = 2;
printf("x is %i, y is %i\n",x,y);
swap(&x,&y); // 記得丟進去的是指向x和y的地址,所以要加&
printf("x is %i, y is %i\n",x,y);
}
void swap (int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
想像你有兩個人要交換手中的兩件物品: