配列を引数にとる関数の定義は,次のようなかんじになると思う.
void f(int a[])
{
/* 処理 */
}
また,次のようにかいても問題ない.
void f(int *a)
{
/* 処理 */
}
というか,前者は後者のシンタックスシュガーでしかない.
int a[8];
a = NULL;
は,コンパイルエラーになるが,
void f(int a[]) {
a = NULL;
}
は,コンパイルエラーにならないことから理解できる.
となると,次のような2次元配列の場合が気になる.
void f(int a[][8])
{
/* 処理 */
}
これは,次の記述と同じ意味になる.
void f(int (*a)[8])
{
/* 処理 */
}
予想と違ったという人も結構いると思う.int *a[8]ではなくint (*a)[8]なのだ.ちなみに,前者は,int型へのポインタの配列で,後者は,int型の配列へのポインタだ.
さて,なんでこんなことになってんだろう.これについては,次のプログラムを見てほしい.
int a[8];
f(a);
何ら変哲のない,配列を関数に渡すプログラムだ.しかし,このとき関数に渡されるのは,本当に配列だろうか?実は,アドレスでしかない.配列として確保された領域の先頭アドレスだ.(知っていると思うけど,aと&a[0]が同じ.)つまり,配列を渡しているというわけではないのだ.
そう考えると,次のような2次元配列のときの説明も容易だ.
int a[4][8];
f(a);
渡しているのは,2次元配列の先頭アドレスである.(aとa[0]と&a[0][0]が同じ.)しかし,2次元配列であるので,列の要素数を知らなければ,2次元配列としてアクセスができないのだ.(列の要素数がわからないと,次の行がどの番地から始まるのか計算できない.)もちろん,2次元以上の多次元配列にも同様のことがいえる.
ということで,こんな風にまとめたわけだけど,間違ってそうで怖いなwC言語に超詳しい人ってざらにいるしw間違ってたら教えてください(*- -)(*_ _)ペコリ
参考文献:
B.W.カーニハン,D.M.リッチー.プログラミング言語C 第2版, 共立出版, 1989.
平林雅英.新ANSI C言語辞典,技術評論社,1997.
0 件のコメント:
コメントを投稿