交換指標指向的整數 題解


交換指標指向的整數 題解

簡潔題意

實作 void int_swap(int *a, int *b);。評分程式會呼叫 int_swap(&a, &b);,呼叫結束後,兩個變數儲存的值必須互換。題目明文禁止呼叫 swap。

函式收到的不是值,是位置

上冊 7.5 講過:函式參數是複本,函式裡改了外面不痛不癢。那為什麼這一題改得動?

關鍵在 11.3 的那句話:位置本身確實被複製了一份,但複本裡寫的還是同一個門牌號碼。函式拿到的 a 是一張紙條,紙條是複本,但上面的門牌號碼跟外面那個變數的是同一個——照著號碼走過去,開的是同一扇門。

所以這一題只有一條規則要記住:

  • 動 a、b:改的是函式手上那張紙條,外面毫無感覺。
  • 動 *a、*b:照著號碼走過去改屋子裡的東西,外面就變了。

要交換外面的兩個整數,動的一定是 *a 和 *b。

為什麼一定要有暫存變數

知道要動 *a、*b 之後,很容易寫成這樣:

*a = *b;
*b = *a;   // 這裡的 *a 已經不是原本的 *a 了

第一行執行完,a 指到的位置已經被 *b 蓋掉,原本的值消失了;第二行再抄回去,只會把同一個值抄兩份。所以要先拿一個暫存變數把原本的 *a 存起來,再依序寫回去——三行的順序不能調換。

每次呼叫只做固定次數的取值與指派,時間複雜度 \(O(1)\)。

參考程式碼

void int_swap(int *a, int *b) {
    int temp = *a;   // 先把 a 指到的值抄一份
    *a = *b;         // b 指到的值,寫進 a 指到的位置
    *b = temp;       // 抄起來的舊值,寫進 b 指到的位置
}

常犯錯誤

  • 寫成 a = b;:只把函式手上那張紙條改成指向 b 的位置,外面的兩個變數一動也沒動。範例 1 會原封不動印出 1 2。
  • 少了暫存變數:*a = *b; *b = *a; 會讓兩個變數都變成原本的 *b。範例 1 印出 2 2。
  • 呼叫 swap:評測會檢查原始碼,直接判「語法限制未通過」,不會進到比對答案那一步。
  • 星號漏一個:int temp = a; 是想把一個位置塞進整數變數裡,連編譯都過不了,錯誤訊息是 invalid conversion from ‘int*’ to ‘int’。

接下來

這一題練的是「照位置把值寫回去」。指標還有另一半的用途——位置本身可以拿來計算,指標之間 就完全不碰值,只算兩個位置差多遠。