<値渡しとアドレス渡し>

 

 関数への引数の渡し方には「値渡し」と「アドレス渡し」があります。引数として、変数に&をつけたものや、配列名、ポインタを渡すケースは、みなアドレス渡しになります。

 

 アドレス渡しは、変数渡しとどこがちがうのでしょうか?一言で言えば、「呼び出し元の変数の中身を、関数側で書き換えることができる」という点です。

 

 つまり、引き出しの例えを使えば、値渡しとは「引き出しの中身だけを関数に渡す」(関数側からは、もともと何番の引き出しに入っていたものかは分からない)のに対して、アドレス渡しは「引き出し番号を関数に伝えて、その引き出しに計算結果をいれてもらう」方法というわけです。

 

(例)

#include <stdio.h>

void summation(int, int, int*);       /* 関数summationのプロトタイプ宣言 */

 

int main(void) {

         int n=2, m=3;

         int a=0;

 

         /* main関数内の各変数の値とアドレスを表示 */

         printf("variables in \"main\" (before function call)\n");

         printf(" n is %d @ %p\n", n, &n);

         printf(" m is %d @ %p\n", m, &m);

         printf(" a is %d @ %p\n\n", a, &a);

 

         summation(n, m, &a);            /* nmは値渡し、aはアドレス渡しでsummationを呼び出し */

 

         /* summation呼び出し後のaの値とアドレスを表示 */

         printf("variables in \"main\" (after function call)\n");

         printf(" a is %d @ %p\n", a, &a);

 

         return 0;

}

 

/* 関数summationの定義 */

/* nnmmの値をaaが指すアドレスに格納 */

void summation(int nn, int mm, int *aa) {

         *aa = nn + mm;          /* aaが指すアドレスにnnmmの和を代入 */

 

         /* 関数summationの中での各仮引数の値とアドレスを表示 */

         printf("variables in \"summation\"\n");

         printf(" nn is %d @ %p\n", nn, &nn);           /* nnの値とアドレス */

         printf(" mm is %d @ %p\n", mm, &mm);           /* mmの値とアドレス */

         printf(" *aa is %d @ %p\n\n", *aa, aa);       /* aaが指す変数の値とaa自身の値(指している変数のアドレス) */

}

 

 上の例では、関数summationを、始めの二つの引数(n, m)を値渡し、3つめの引数(&a)をアドレス渡しして呼び出しています。

 

 呼ばれた関数側は、アドレスを受け取るわけですから、ポインタ変数を仮引数としておく必要があります。mainから呼び出された時に、このポインタ仮引数にあるアドレスが代入されます。上の例では、summation関数内のポインタaaに、呼び出し時にmainの中の変数aのアドレスが入れられます。従って、関数内部でこのアドレスに計算結果の値を書き込む(*aa = nn+mm;)と、mainのなかの変数aの値が書き換わることになります。

 

 このプロクラムを実行すると、例えば以下のように表示されます。mainの変数aのアドレス(0xbffffaa8)が、summation関数内のaaに渡されている様子が分かります。

 

 (実行結果の例)

variables in "main" (before function call) main内での変数(呼び出し前)

 n is 2 @ 0xbffffaa0            nの値とアドレス

 m is 3 @ 0xbffffaa4            mの値とアドレス

 a is 0 @ 0xbffffaa8            aの値とアドレス

 

variables in "summation"       summation関数内の変数

 nn is 2 @ 0xbffffa78          nの値をnn格納(nとは別アドレス)

 mm is 3 @ 0xbffffa7c          mの値をmmに格納(mとは別アドレス)

 *aa is 5 @ 0xbffffaa8         aのアドレス(aa)に計算結果を格納

 

variables in "main" (after function call) main内での変数(呼び出し後)

 a is 5 @ 0xbffffaa8            関数呼び出し後はaの値が変わっている。

 

 

戻る