低レベルなヒトの覚え書き

●余談、のようなもの


2. もしかしたら、LSI-Cは初心者向きではないかもしれない

註: ここでいう「LSI-C」とは「LSI C-86 Ver 3.30c 試食版」、「BCC32」とは「Borland C++ Compiler 5.5.1(無料版)」のことです。

(1) イントロ

筆者は現在、メインのCコンパイラとして、LSI-Cを使用しています。 いまどきわざわざLSI-Cを使う理由は、「自分が現役のDOSユーザーだから」「DOS用にしておけばWindowsでも使える」「しかもLSI-CならDOS汎用」「どうせそんなに大きなものはつくらない(つくれない)」「何といっても無料だ」「Turbo Cの無料版は日本語が使えない」などです。
LSI-Cのほかには、BCC32を使ってます。 BCC32を選んだ理由は、無料で配布されている32ビットのCコンパイラのなかでは、いちばんお手軽そうだったからです。 もともとは他人様のソースをいじるために導入したのですが、最近はもっぱら自作のプログラムの問題点を探るために利用しています。

(2) 文法チェッカーとしての機能

DOS用のソフトしか作らない筆者が、自作のソースの内容のチェックを、LSI-CとBCC32で二重に行なうようにしている理由は、率直に言って、前者だけでは頼りないと感じているからです。
たとえば、リスト8のようなプログラムがあるとします。 このプログラムをBCC32でコンパイルすると、「'Y' に代入した値は使われていない」と、「宣言された 'X' は使われていない」という、2つの警告が表示されます。 それに対して、LSI-Cのほうは、「'X' not used」だけです。 変数Yの件は問題とされません。

[リスト8]
 | int main() {
 |   char X, Y;
 |   Y=0;
 |   return 0;
 | }

おそらく、LSI-Cが変数Yの件を問題としないのは、それなりに理由のあることなのでしょう。 ただ、筆者のような下っぱのユーザーにしてみれば、改善可能な点があるなら、出し惜しみせずに指摘してほしいわけです。 そういう意味では、明らかにBCC32のほうがユーザに対して親切だと思います。
筆者の普段の経験のなかでも、こうした食い違いが生じることは、けっしてめずらしいことではありません。 しかも、食い違いが生じた場合は、ごく例外的なケース(次節参照)を除いて、必ずBCC32のほうがLSI-Cを補うような形になっていました。
ソースリストの文法チェックを複数のコンパイラで行なうことは、一般的にも、それなりに意味のあることだと思いますが(可搬性の確保とか)、LSI-Cのユーザーにとっては、なおさら大切なことではないかと考えています。

(3) ちょっと寄り道: charとintの解釈

ところで、LSI-CとBCC32では、charやintという型の解釈が若干異なります。 LSI-Cのcharはunsignedですが、BCC32のcharはsignedです。 同様に、LSI-Cのintはshortですが、BCC32のintはlongとされています。 C言語の規格上は、どちらでもいいことになっているのだそうです。 ややこしくてかないません。
こうした変数の型の解釈の違いが、前節で述べたようなソースの評価の食い違いにつながる場合もあります。 この場合の警告は、特に気にする必要のないものといえますが、そうかといって、単純に無視することもできません。 なかには本当のミスが混在しているかもしれないからです。
幸い、というべきか、BCC32のcharに関しては、設定を変更するためのオプションが用意されています。 ただし、intのほうは、どうしようもありません。 結局は、ひとつずつ確認せざるを得ないので、警告の数が多いときは鬱陶しいです。

(4) 安全装置、なの?

話を本筋に戻します。
実は、警告の少なさに見られるLSI-Cの「寛容さ」は、コンパイルの結果として生み出される、実行ファイルの動作にまで影響を与えている可能性があります。
筆者がそう思うようになったきっかけは、次のような出来事です。

「プログラムを書いた」
→「LSI-Cによるコンパイルはノーエラー」→「できあがった実行ファイルは順調に動作」
→「BCC32によるコンパイルもノーエラー」→「ところが、こちらの実行ファイルは試験中に暴走」
→「調べてみたら、確かにソースに欠陥があった」

要するに、普通に考えたら暴走して当然のプログラムが、LSI-Cでコンパイルしたら、なぜかうまいこと動作しちゃってたわけです。 しかも、筆者の経験では、そんなことが何度かありました。 ちょっと偶然とは思えません。
まあ、何はともあれ、動くんだったらそれでいい、という場合もあるとは思います。 でも、基本的には、ミスをしたらミスをしたと教えてくれるほうが、ユーザーにとってはありがたいはずです。 とりわけ、筆者のような低レベル者にとっては。

[追記]
実際の例として、このページを更新する少し前には、こんなことがありました。

「配列のためのメモリをmallocで確保するプログラムを書いた」
→「たいしたサイズでもないし、思い直して自動変数に変更した(変数名は同じ)」
→「LSI-Cでは、コンパイルも動作も問題なし」
→「BCC32によるコンパイルもノーエラー」→「しかし、実行してみると、途端にエラーで停止」
→「調べたら、freeを削除し忘れていた」

BCC32のほうも、コンパイル自体はノーエラーで完了しているわけで、その点はちょっと情けない気がしますが、自動変数に対するfreeを平然と受け流してしまうLSI-Cは、大物なんだか抜けてるんだか、よくわかりません。

→トップ


R.2: 2006/08/01
Copyright (C) 2005,2006 A.Satoshi