Wednesday 1 November 2006

昨日の日記は忘れました



ひさしぶりに、コンパイラのバグ取りにはまってました。

 struct hoge a;
 void f(struct hoge a);

ってのは構造体全部がコピーされてfに渡されるわけなんだけど、

 int v[10][10];
 void h(int v[10][10]);

ってのは、配列へのポインタしか引き渡されない。それは、

 void g();
 void k(void g());

で、g の本体がコピーされて渡されるわけではないのと同じ。

C では値渡しが基本だから、この二つだけを、特別扱いしている。
 typedef int V[10][10];
 void h(V x);

とかだと、ポインタ渡しには見えないよな。うっかり値渡しに直してしまって、生成されたコードを見てみたらポインタ渡しだった。何故だか、しばらく考えちゃったよ。

C の仕様の変態さの一つなんだけど、一概に悪いってわけでもない。このあたりって「形式的な綺麗さより、実用を取るぜ」みたいなところがある。まぁ、配列と配列へのポインタを意図的に混同したのがいけないといえばいけないんだけど。でも、いちいち、

 (*a)[5][5]

って書くのは嫌だってのは、その通りだよ。

Perlでは、

 $a->[5][5]

とか書くけどね。

  DB<1> $a->[5][5]=3

  DB<2> p $a
ARRAY(0x180815c)
  DB<3> p @$a
ARRAY(0x224a14)
  DB<4> p @{$a->[5]}
3

みたいなのを汚いと思う人は多いだろうが.... C では a->[5] は採用されなかったんだよな。Perl のこれを見たときには、「なるほど」と思うより「え、なんで?」と思った記憶があるので、その時点では、Cの配列と配列へのポインタの構文的な混同に気づいてなかったということらしい。

No comments: