第27回
データ構造(6)~ポインタを使った引数の受け渡し

数値をポインタで渡す

これまでに、ポインタと文字列(char型配列)は相性がよく、文字列の処理ではポインタが大活躍することを説明しました。そして前回(第26回 データ構造(5)~ポインタを使った文字列処理関数を作る)、その例として文字列を扱う関数をいくつか紹介しました。

もちろん、文字列以外の型に対してもポインタは使えます。数値型を扱う関数で、ポインタを使って引数を渡すとどうなるのか見てみましょう。

引数を2乗する関数

まず、整数型の引数を2乗する関数isquareを作ってみます。処理を分かりやすくするため、ここでは変数をint型とします。リスト1のような形が一般的でしょう。引数nにn自身を乗算し、その結果を関数の戻り値とします。

この関数は、以下のような形で使用できます。
int x, ans;
x = 10;
ans = isquare(x); ---- 変数ansにxの2乗が代入される

これで、変数ansにはxの保持している値10の2乗である100が代入されます。isquare関数の引数とした変数xの値は変わりません。isquare関数にはxという変数そのものではなく、『変数xの保持している値』だけが渡されるからです。

リスト1:引数の値を2乗して返す関数
int ipower(int n)
{
  return(n * n);
}

仮引数と実引数

リスト1の
int isquare(int n)
のnのように関数の定義で示される引数を「仮引数」と言い、上のソース
ans = isquare(x);
のxのように実際に関数を呼び出すときに与える引数を「実引数」と言います。関数定義時の仮引数は、与えられた引数の値を関数内でどのように処理するかを記述するための『仮の入れ物』であって、その関数が呼び出されたとき実際に処理される値は呼び出し側で設定する実引数である……ということです。

このことは、値の入れ物──変数の扱いが仮のものか実際の処理対象なのかという意味上の区別を指しているのであって、関数内で処理されるのは変数の保持している「値」でしかありません。

引数を書き換える関数

では、関数isquareをリスト2のように定義するとどうなるでしょう?

この関数は値を返しません。その代わり、仮引数が*の付いたint型のポインタになっています。引数がポインタの場合、実際に関数を呼び出す際には変数のアドレスを設定します。アドレス取得演算子&を変数名の前に記述すれば、変数のアドレスが取り出せます。

従って、リスト2の関数は以下のようにして呼び出します。変数ansの前に&記号が付いていることに注意してください。
int ans = 10;
isquare(&ans);

これで、変数ansの保持している値が、関数を呼び出した後には2乗されて100になっています。リスト1の場合とは異なり、引数に設定した変数の保持する値そのものが書き換えられています。

リスト2:引数の示す変数の中身を2乗する関数
void ipower2(int *n)
{
  *n *= *n;
  /* '*n'(nの示す場所の値)に*nを乗算する */
}