わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

ポインタのポインタの使い道

しかし,ポインタのポインタはいったいどのような使い道があるのだろうか.知人に聞いたら,どうも文字列を関数の引数に渡す場合などに使えるらしい.そこで次のプログラムを作ってみた.
(略)
ポインタのポインタが本当に必要となる場面は,どのような場合があるだろうか.筆者の無い頭をひねっても何も出てこない.
(ここが変だよC言語〈上〉, pp.210-211)

上で略したところには,「char *brother[] = {"一郎","花子","次郎","桃子"};」として,ポインタのポインタとなる変数brotherを定義し,関数に渡して文字列を順にin sequence出力するプログラムが書かれています.
「文字列の並び」をCで処理するときに,そのデータ構造として,

  • 固定長文字列の固定長配列(二次元配列,char array1[5][10];)
  • 固定長文字列の可変長配列(配列のポインタ,char (*array2)[10];)
  • 可変長文字列の固定長配列(char *array3[5];)
  • 可変長文字列の可変長配列(ポインタのポインタ,char **array4;)

が考えられます.ただし3番目のケースはほとんど見かけませんが.
可変長文字列の可変長配列(ポインタのポインタ)には,文字列長や(文字列の)配列サイズを柔軟に変えられるというメリットがあります.とはいえ,「プログラマに苦労を強いられる」,あるいは「バグが発生しやすい」というリスクもあります.処理対象となるデータに応じて,どれを採用するか決めるべきでしょうね.
なお,コマンドライン引数をとるとき,mainの第2引数に書くargvも,charのポインタのポインタとなります.すなわち可変長文字列の可変長配列です.argvが参照する文字列を書き換えることは問題ありませんが,文字列を伸ばしたり,要素数を増やたりしたいとなると,別に領域を確保してコピーするなどの作業が必要になります.
ポインタのポインタを使う全く異なるシーンとして,「&ポインタ変数」を関数呼び出し時に引数として与え,関数の中で,ポインタ変数の値(指し示す先)を書き換えるというものがあります.このとき,関数の仮引数は,ポインタのポインタとして定義します.利用例は,昨日のエントリをご覧ください.