ちょっと大きめのプログラムを開発すると、たいがい、大いに頭を抱え込む質の悪いバグにぶつかる。原因が分かってしまえばどうという事もないたわいの無い事がほとんどであるが、見つけるまでは大変である。特に思いこみによる勘違いが原因である場合には、それが顕著であるように思う。
C言語では配列とポインタが本質的に同じであるということはよくご存知のことと思いますが、さて、やらかしたヘマは次のようなもの。
最初のコーディングでは2次元配列を静的に確保していた。
static char buf[MAXL][MAXCHAR]; func() { ・・ strcpy(buf[1], "ABCDEFGHIJKLMN"); のように buf にアクセスしてました。 ・・ }
これをプログラム実行中に配列領域を確保させるつもりで次のように書き直した。
static char **buf; ( char *buf[]; とも書けますが) func() { buf = (char **)malloc(MAXL * MAXCHAR); ・・ strcpy(buf[1], "ABCDEFGHIJKLMN"); ・・ }
この変更はコンパイルエラーにもならず一見正しいようなのですが、これが大きな間違いであるということに気づくのに2〜3日かかってしまいました。冷静になって考えればなぁーんだという事なんですが、頭が熱くなっている時は全然このミスに気がつきませんでした。全然別の所を一生懸命調べていました。
正しい記述は今日は控えますが、このミスの原因は、一次元配列 buf[]; が *buf;の書換えで殆ど問題が無いことと、main 関数の引数である *argv[](**argv でも同じ)について if(argv[1][0] == '-') のように2次元配列参照をよくやることからくる思いこみによります。配列参照は * によるポインタ操作と全く等価なのですが、ポインタ変数の宣言には気を付けなくてはいけません。特に2次元以上の配列参照を行うためのポインタである時にはです。
どこに問題があるかすぐに指摘できる人には、Cをよく使いこなしている人だな、と脱帽します。