ポインタのお話〜どこもかしこもポインタなのかも〜

【どこもかしこもポインタなのかも】

変数ばかりがポインタで扱えるわけではありません。
値を入れる器はすべてポインタで扱うことができます。

変数以外にそんなものあるの?
あるんですね。今までの話の中で、ヒントがあります。

  • ヒント1 : 作業場の話
  • ヒント2 : 関数の戻り値の話

正解は「関数」です。
関数もポインタで扱うことができるのです。
関数という名前の大きな器に値が入っているのです。
# 値がない場合もありますが…。

どんな時に使うのでしょう?
あまり使う機会はないと思いますが、Windowsプログラムではコールバック関数なんてものがありますから、このあたりで使っているといえますね。

【ポインタ値が関数の戻り値であるときの注意点】

時によってはポインタ値が関数の戻り値となる場合があります。
char *strchr(char*, int) 関数などがその例です。

このような関数を作る場合には、少し注意が必要です。
理解の手助けのためには、まず【スコープって何?】の項目をちょっと先に読んでおいて下さい。

例:やっちゃいかんこと

 void fnk_Main(void){
   char *pcData;

   pcData = fnk_Sub();
    :
  }

 char *fnk_Sub(void){
   char cData[10];
    :
    :
   return cData;
 }

さて、この例ですが、なぜやってはいけないことなのでしょう?

step 1.
fnk_Main関数が呼び出されました。

  fnk_Main     fnk_Sub
  pcDataの用意  まだ姿はなし
   ┃┃
   ┗┛

step 2.
fnk_Main内部でfnk_Sub関数が呼び出されました。

  fnk_Main         fnk_Sub
  fnk_Subの呼出 → cDataの用意
   ┃┃             ┃┃
   ┗┛             ┗┛

step 3.
fnk_Subの処理が終わり、fnk_Subで得られた結果をfnk_Mainに返します。

  fnk_Main         fnk_Sub
  fnk_Subから      cDataのアドレス値を
  値をもらう       戻り値として返す
   ┃┃← cData── ┃┃
   ┗┛             ┗┛

step 4.
fnk_Sub関数を終了します。

  fnk_Main         fnk_Sub
                   関数ごと破棄される
   ┃┃
   ┗┛

step 4.の状態のとき、fnk_Sub関数にあったcDataという変数はどうなったのでしょう?
もう要らなくなったとして処分されてしまうんですね。
ここで、この変数の器の番号を示すアドレス値は自分自身を器であると認識しなくなってしまいます。(ちょっと語弊はあるかも…。)
この時、処分されてしまった変数のアドレス値を持っているfnk_Main関数のpcDataはなくなってしまったはずの器を示していた部分を勝手に器として勘違いしてしまう事になるのです。

これはちょっと困った事…。
器ではないところを器だと勝手に思ってしまうようなプログラムは落ちるプログラムを作ってしまう事になってしまいます。

この事にちょっと気をつけてプログラムを組んでいきましょうね。