オルタナティブ・ブログ > mtaneda ブログ >

中小企業の開発者は会社で何をしているのか

本当は怖い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言語でした。
Comment(0)