本当は怖いC言語?
»
昨日も書きましたが、メンバーとともにZ80を使っています。
そんな中、メンバーから「コンパイラがバグってる」と報告を受け、
一緒にコンパイル結果を眺めていました。
以下実例
extern int *varX; int *varY; void func() { varY = varX; }
結果
PUBLIC func_ CSEG %4 "ptest.c" 0 func_: %5 1 LD HL,(varX_) LD (varY_),HL %6 0 RET EXTRN varX_ DSEG PUBLIC varY_ varY_: DS 2 END
ここで、LD HL,(varX_)は、ポインタが欲しいのに間接参照している、
ダメじゃないか!?
と言う話しになったわけです。
最初に言っておくと、これはメンバーの勘違いで、私もそれにつられてしばらく、
コンパイラのバグと思ってしまいましたが、実はコンパイラは全く正常でした。
varXは、extern int *varX と宣言されているので、
ポインタを格納できる変数です。
ということは、欲しいアドレスはvarXという名前がついたアドレスに格納されているわけなので、
LD HL,(varX_)で正しいわけです。
何故こんな初歩的なことを勘違いしたかというと、
extern int *varXの実態は、
別のアセンブリ言語で書いたファイルで、varX_ という名前で定義されていました。
この場合、C言語側からみると、varX_はポインタを格納できる変数です。
しかし、アセンブリ言語側では、varX_を配列としてコードを書いていました。
そのため、コンパイラと同じように扱って欲しければ、
extern int varX[] と書かなくてはならないのでした。
こうすれば、コンパイラは LD HL,(varX_)ではなく、LD HL,varX_とコンパイルし、
目的の結果が得られるのです。
わかれば本当に初歩的なことですが、
たまに勘違いをすると、本当は怖いC言語でした。
SpecialPR