int 型や float 型の引数を普通に渡すのが値渡し。このとき引数の値はコピーされて関数に渡されるので、関数の中で変更しても元の(つまり関数の外の)変数の値は変化しない。
これに対して、ポインタで渡すのが参照渡し。引数のポインタの持っているアドレスがコピーされて関数に渡されるけど、このアドレスは関数の呼び出し元のポインタと同じデータを指している。結果として、関数内で引数(ポインタ)の指すデータを変更すると、呼びさし側でもデータが変化することになる。
参照渡しの場合は、関数の仮引数をポインタとして定義する。次のプログラム中の関数 swap は2つの引数(ポインタ)をとって、相互に値を交換する。
#include void swap(int *i, int *j); int main(void) { int num1, num2; num1 = 100; num2 = 800; printf("num1= %d, num2= %d\n", num1, num2); swap(&num1, &num2); printf("num1= %d, num2= %d\n", num1, num2); return 0; } void swap(int *i, int *j) { int temp; temp = *i; *i = *j; *j = temp; }
「void swap(int *i, int *j)」というのが、ポインタ引数の書き方だ。ここでは2つ使っている。
実行結果:
takatoh@nightschool $ ./sample_7_3 num1= 100, num2= 800 num1= 800, num2= 100
ちゃんと num1 と num2 の値が入れ替わった。
ところで、引数に配列(文字列を含む)を渡す場合、配列のアドレスが渡されるだけで配列そのものがコピーされるわけじゃない。これは参照渡しだ。だから、関数の仮引数はポインタ型として定義する必要がある。
#include void f(int *num); int main(void) { int count[5] = {1, 2, 3, 4, 5}; f(count); return 0; } void f(int *num) { int i; for (i = 0; i < 5; i++) { printf("%d\n", num[i]); } }
takatoh@nightschool $ ./sample_7_3a 1 2 3 4 5