定義兩個函數嘗試交換 int i=0, j=1:
s(int*, int*) — 嘗試交換**指標變數本身**(地址值)s2(int*, int*) — 交換**指標指向的記憶體內容**#include <stdio.h>
void s(int *i, int *j); // 嘗試交換指標變數
void s2(int *i, int *j); // 交換所指內容
void p(int i, int j); // 印值
void pp(int *i, int *j); // 印址
int main() {
int i = 0, j = 1;
p(i, j); // 0 -- 1
pp(&i, &j); // 0xbfe2fccc -- 0xbfe2fcc8
s(&i, &j); // 嘗試交換指標
p(i, j); // 0 -- 1 【值未變】
pp(&i, &j); // 位址未變
s2(&i, &j); // 交換內容
p(i, j); // 1 -- 0 【值交換成功】
pp(&i, &j); // 位址仍未變
return 0;
}
void s(int *i, int *j) {
int tmp = *i;
i = j; // 只改區域副本 i
j = &tmp; // j 指向區域變數 tmp(危險!函數返回成懸空指標)
printf("address change\n");
p(*i, *j);
pp(i, j);
}
void s2(int *i, int *j) {
int tmp = *i;
*i = *j;
*j = tmp;
}
void p(int i, int j) { printf("%d -- %d\n", i, j); }
void pp(int *i, int *j) { printf("%p -- %p\n", (void*)i, (void*)j); }
0 -- 1
0xbfe2fccc -- 0xbfe2fcc8
address change
1 -- 0
0xbfe2fcc8 -- 0xbfe2fc9c ← s 內部 tmp 位址(已失效)
0 -- 1
0xbfe2fccc -- 0xbfe2fcc8 ← 回到 main,i/j 位址值未變
1 -- 0
0xbfe2fccc -- 0xbfe2fcc8 ← s2 真正交換了內容
| 傳遞方式 | 能改變實參的值? | 能改變實參的位址? |
|---|---|---|
傳值 void f(int x) | 否(改副本) | 否 |
傳指標 void f(int *p) | 是(*p = ...) | 否(p = ... 只改副本) |
傳指標的指標 void f(int **p) | 是 | 是(*p = ...) |
C++ 參考 void f(int &r) | 是 | 否(參考綁定後不可重綁) |
main 棧框: i @ 0xbfe2fccc (值 0)
j @ 0xbfe2fcc8 (值 1)
s(&i, &j) 棧框: i (區域副本) @ ... 初值 0xbfe2fccc
j (區域副本) @ ... 初值 0xbfe2fcc8
→ i = j 只把區域 i 改成 0xbfe2fcc8
→ j = &tmp 把區域 j 改成 tmp 位址
→ 函數返回,區域銷毀,main 的 i/j 完全不受影響
int**)或參考到指標(int*&)。j = &tmp)。