C 語言初學教材 - 第五章 數字對調

先來想想如何進行兩個變數的數字對調,我們其實在氣泡排序法已經用過了。例如以下假設 a 、 b 、 temp 都是整數變數,然後將 a 與 b 所儲存的值對調

temp = a;
a = b;
b = temp;


簡單說,就是先把變數 a 的值暫存到 temp ,然後將 b 的值存到 a 之中,最後再將 temp 的值回存到 b 之中。


那要怎麼把這個功能寫成函數呢?直接照上面的方式寫可以嗎?
#include <stdio.h>

void swap(int n1, int n2);

int main(void)
{
    int a = 3;
    int b = 5;
    
    printf("a = %d, b = %d\n", a, b);
    swap(a, b);
    printf("呼叫 swap() 之後, a = %d, b = %d\n", a, b);
    
    return 0;
}

void swap(int n1, int n2)
{
    int temp = n1;
    n1 = n2;
    n2 = n1;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:swaptestw.c
    功能:將兩個數字對調,錯誤的例子
    作者:張凱慶
    時間:西元2010年7月 */


編譯後執行,結果如下



編譯執行的結果直接給我們答案了,為什麼呢?因為 C 語言是採用傳值呼叫,任何傳遞到函數中的參數都是拷貝後的值,所以變數 a 與變數 b 傳遞給函數 swap() 也是拷貝後的值,也就是 n1 及 n2 。 n1 及 n2 在 swap() 中做了什麼調整或改變,這都侷限在 swap() 裡頭,並不會影響到 main() 裡的 a 及 b 。


如果我們要利用函數對調兩個變數的值,我們應該要利用指標做參數,因為指標能將變數的記憶體位置變數傳遞給函數,然後在對調函數中用取值運算子得到變數所儲存的值,進行兩個變數的對調工作。


正確的版本如下
#include <stdio.h>

void swap(int *n1Ptr, int *n2Ptr);

int main(void)
{
    int a = 3;
    int b = 5;
    
    printf("a = %d, b = %d\n", a, b);
    swap(&a, &b);
    printf("呼叫 swap() 之後, a = %d, b = %d\n", a, b);
    
    return 0;
}

void swap(int *n1Ptr, int *n2Ptr)
{
    int temp = *n1Ptr;
    *n1Ptr = *n2Ptr;
    *n2Ptr = temp;
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:swaptest.c
    功能:將兩個數字對調
    作者:張凱慶
    時間:西元2010年7月 */


第 3 行及第 17 行,宣告指標變數用星號
void swap(int *n1Ptr, int *n2Ptr);


第 11 行呼叫
swap(&a, &b);


利用取址運算子 & 可取得變數的記憶位址,也就是指標變數。


第 19 到 21 行
int temp = *n1Ptr;
*n1Ptr = *n2Ptr;
*n2Ptr = temp;


函數 swap() 裡的 n1Ptr 儲存的是變數 a 的記憶體位址,所以要利用取值運算子 * ,反參考該位址所儲存的數值, n2Ptr 的情況也一樣。這樣一來,便可由被呼叫函數操作呼叫函數中的變數值,兩個變數的數值才能對調。


編譯後執行,結果如下



問題與討論
  1. 暫存變數的作用是什麼?
  2. 為什麼到另一個函數之中,不能把函數 main() 裡的數字對調?
  3. 說明利用指標三倏地運作機制。




沒有留言: