int a[4][4];の場合で考えていきましょう。
自分でプログラムを書いてもいいですし、 こちらのプログラム(data_C.c) で試してもいいですから、debugger などで各種データにアクセスしたり、アドレスを見たりしてみましょう。
一方で、
int * b[4];というのは、「intへのポインタ」の配列です。ポインタ用の領域が 4 つ分とられるだけです。 例えば、以下のプログラム(data_E.c)の場合、 先ほどつくったa[4][4]の各a[0],a[1],a[2],a[3] (int の配列)のデータを格納してみました。
int main(int argc, char** argv) { int a[4][4]; int* b[4]; int i = 0; for(; i < 4; i++) { b[i] = a[i]; } return 0; }イメージはこんな感じ。int a[4][4] と int * b[4]では、 全然感じがちがうでしょう?
多重配列と話はずれるんですが、main(int argc, char** argv)の argv も bとイメージは似ています。 コマンドラインから与えられた引数などが文字列として、格納されています。 で、それらの文字列に相当するchar*達への配列が準備されていて、 argv は、その配列を示しているという訳です。だから char** argv あるいは、char * argv[]とか書かれるわけです。
実際に、デバッガなどで、様子を確かめてみると理解がすすむでしょう。
教科書("K&R")の P139 とかみてみましょう。
2001.11.12/ Tomio KAMADA: kamada@cs.kobe-u.ac.jp