導入
関数に「値」を渡すと、関数の中で書き換えても呼び出し元は変わりません(コピーが渡るため)。ポインタ(住所)を渡すと、呼び出し元の変数そのものを書き換えられます。
説明
まず、ふつうに値を渡した場合。関数には値のコピーが渡るので、中の変更は呼び出し元に届きません。
#include <stdio.h>
void tryChange(int x) {
x = 100; // これはコピー(別の箱)を変えているだけ
}
int main() {
int a = 5;
tryChange(a);
printf("%d\n", a); // 5(変わらない)
return 0;
}
a と、関数の中の x は、メモリ上の別々の箱です。だから x をいくら変えても a には影響しません。
flowchart LR a["mainのa = 5<br/>(3000番地)"] -->|"値をコピー"| x["tryChangeのx = 5→100<br/>(別の箱 5000番地)"] x -.->|"元のaには届かない"| a
ポインタ(住所)を渡すと、* を通じて呼び出し元の変数を直接書き換えられます。住所を渡す=「本物の場所を教える」ので、関数はその場所を直接いじれます。
#include <stdio.h>
void addOne(int *x) {
*x = *x + 1; // 住所の先=呼び出し元の変数を書き換える
}
int main() {
int a = 5;
addOne(&a); // aの「住所」を渡す
printf("%d\n", a); // 6(変わった!)
return 0;
}
flowchart LR a["mainのa = 5→6<br/>(3000番地)"] -->|"&aで住所を渡す"| x["addOneのx = 3000<br/>(aを指すポインタ)"] x -->|"*xで書き換え"| a
2つの変数の中身を入れ替える swap も、ポインタを使えば作れます。値渡しでは絶対にできない処理です。
#include <stdio.h>
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
int main() {
int x = 1, y = 2;
swap(&x, &y);
printf("%d %d\n", x, y); // 2 1
return 0;
}
やってみよう
addOne を *x = *x + 10; に変えたり、swap に渡す値を変えたりして、呼び出し元が書き換わることを確かめましょう。tryChange(値渡し)と addOne(ポインタ渡し)を見比べると、違いがはっきりします。
演習
int n をポインタで受け取り、その値を2倍にする関数 doubleIt を定義してください。int a = 8; doubleIt(&a); のあと a を表示すると 16 になります。
ヒント1を見る
void doubleIt(int *x) { *x = *x * 2; }、呼び出しは doubleIt(&a);。