ポインタを引数にする書き方

ポインタは、変数であるため、関数の引数とすることもできます。

戻り値の型 関数名 ( 引数の型 *引数 )
{
}

ポインタ型変数の宣言と同じように、「*」を付けて引数を宣言します。
では、サンプルプログラムを見てみましょう。

スポンサーリンク

サンプルプログラム

ソースファイル名:main.c

実行方法

上のソースを書き写して実行してください。
各関数を通過した後の a の値の違いに注目してください。

関数内での値の書き換え

今までは、関数を使った変数の値の書き換えは、戻り値を変数に入れることで行っていました。
しかし、ポインタを使うことで、戻り値を使わなくても関数内で変数の値を書き換える事ができるようになります。 今回、例の

void ChangeValue( char *ptr )
{
  *ptr = 100;
}

では、引数として、char 型のポインタを指定しています。
サンプルプログラムでは、a の変数のアドレスを渡しています。

つまり、ChangeValue の引数 ptr には変数 a のアドレスが入っていることになります。

*ptr = 100;

は、ptr のアドレスの値を 100 にしろという意味になります。
ptr は、main 関数内の変数 a のアドレスが入っているので、a の値を 100 にしろと言う意味になります。

このように、ポインタを使うことで、戻り値を使用しなくても変数の値を書き換える事ができるようになります。

ポインタ型の引数の特徴とは?

そもそも、引数をポインタにすると何が違うのか?

void function1( char arg1 )
{
  arg1 = 100;
}

サンプルプログラムでは、function1 は、arg1 という名の引数を使っています。
そして、main 関数からは、a が引数として渡されています。

arg1 は、a の値を渡しているので、arg1 を書き換えたら a の値も変わると思ってしまいますよね。 これは間違いで、arg1 の値を変えても a の値は変わりません。

この a と arg1 は同じ値になるのですが、別のメモリとして割り当てられています。
つまり、別のアドレスを持っているわけです。
従って、いくらこの arg1 を書き換えても、a の値は変わりません。
サンプルプログラムでは、function1 の中で arg1 に 100 を入れているのですが、これは全く無意味な処理です。 関数を抜けた後、a の値を確認するとわかるのですが、10 のままになっているはずです。

void change_value( char *ptr )
{
  *ptr = 100;
}

では、change_value はどうかというと、こちらは引数としてポインタ型の変数を宣言しています。 そして、main 関数の呼び出しの時は、

change_value( &a );

として、変数 a のアドレスを渡しています。
function1 の時と同様に、ptr と a は別のメモリに割り当てられてしまいます。 ただ、ptr は a のアドレスを保持しているので、そのアドレスの値を書き換えれば結果として、a の値が変わることになります。 サンプルプログラムでは、

*ptr = 100;

を通過した時点で、main 関数内の変数 a の値は 100 に変わります。

ポインタ型の引数は何が便利なの?

ポインタ型の引数を使うことで、値を関数内で変更することができます。 これは何が便利かというと、以下の二つがあります。

  1. 戻り値を複数にできる
  2. 関数内で呼び出し元変数の値を書き換えれる

戻り値を複数にできる

関数を作っていると、戻り値を二つにしたい時が出てきます。 そういうときは、

とすれば、戻り値で b に値を代入するだけでなく、a にも値も代入することができます。

関数内で呼び出し元変数の値を書き換えれる

前にも書いているのですが、呼び出し元の変数の値を書き換えれることができます。

外部変数であれば、どんな関数からでも値の書き換えが可能なのですが、内部変数は適用範囲がその関数内なので他の関数で値を書き換えることができません。

しかし、サンプルプログラムでも行っている通り、アドレスを他の関数に渡すことで、他の関数でも値の書き換えが可能になります。

スポンサーリンク