交換指標指向的整數 題解
交換指標指向的整數 題解
簡潔題意
實作 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’。
接下來
這一題練的是「照位置把值寫回去」。指標還有另一半的用途——位置本身可以拿來計算,指標之間 就完全不碰值,只算兩個位置差多遠。