アドバンスドな話

更新日:2004-04-06、趙

◎コンパイルエラー

文法に合わないプログラムは、コンパイルの段階でエラーとなります。例えば、以下のプログラムをコンパイルしてみましょう。

 #include <stdio.h>
 
 int main(void) {
         printf("Hello, world.\n);
 }

コンパイルしたら、以下のような結果図になるでしょう。

gcc compiling error

日本語に訳すと、

 hello.cの4行目16列目(※ printfの最初の " ):終了の " がない。
 hello.c:main関数において、
 hello.cの5行目:エラー:"return"の前に文法エラーがある。

というものですね(英語が苦手?英語は、プログラマにとって必須なものよ。まあ、似たような単語ばかりで何回も出会うと分かりますが)。プログラムのミスが分かりました?

参考にclでコンパイルしてみました。今度は日本語に訳さなくていいですが、ミスがどこ?

cl compiling error

では、上記のソースを直してください。コンパイルが成功するまで。

◎デバッグ

コンパイルが成功しても、プログラムは"正しく動く"とは限りません。正しく動かないプログラムを、正しく動くように修正するのは、デバッグ(バッグ取り)といいます。Cプログラムは、一発完成のことが珍しく、殆どデバッグが必要と言っても過言ではないでしょう。

以下、私が自分のプログラミング経験から得られたデバッグテクニックを述べます。

1)最も重要なのは、自分の考え方が正しいかどうかを検討すること。

つまり、あなたがプログラムに与えた動き自体は本当に正しいのかということです。経験では、多くのバッグは、プログラミング上のミスではなく、自分の思ったことが最初から間違っていたことに起因しています。よって、プログラムを調べる前に、頭の中に実行様子をシミュレーションしてよく検討してください。

経験1:まず、自分の考え方をじっくり検討すること。

2)コンパイラの警告をよく考えよう。

これは(チェックの甘い)C特有かもしれませんが、コンパイラの警告レベルをあげることによって、ミスが検出されることがよくあります。gcc の場合、オプション -Wall を追加してコンパイルしましょう。例えば、以下の認証プログラムをコンパイルしてみましょう。

 #include <stdio.h>
 
 int main(void) {
     int secret = 123456; /* password */
     int key;
 
     printf("パスワードを入力してください。");
     scanf("%d", &key);
     if (key = secret) {
         printf("合ってます。\n");
     } else {
         printf("合ってません。\n");
     }
     return 0;
 }

コンパイル図

wall.png

オプションなしの場合は、警告もなかったのですが、オプション"-Wall"をつけると、

pass.c:関数mainにおいて:
pass.c 9行目:警告:真の値として使われた代入式に括弧をつけよう。

"=="という比較式(if (key == secret) ...)のつもりですが、"="という代入文になってしまったことがもうお分かりですね。因みにこのミスは、上級者でもしばしばします。

経験2:変なコンパイル警告がなくなるまでプログラムを検討しよう。

3)プログラムがデバッグ情報を出力するようにすること。

それにしてもうまく動かない場合は、プログラム上で、診断情報(変数の値、比較式の真偽、プログラムの流れ、関数の戻り値等等)を出力する方法を覚えましょう。この方法は、余分のコードを入れなくてはならないから非効率と思われるかもしれませんが、少なくとも私が20年間勉強した10種類以上のプログラミング言語において共通に使える、唯一つの手段のことを覚えてください。これが上手に使えたら、どんな言語でも容易にマスタできるようになります!

経験3:プログラムで診断情報を出力しよう。

また、C-like(C、C++、Java等)の言語には、assert という非常に有用なものがあります。参考資料を調べて、条件付のコンパイルと一緒にassertの使い方を覚えましょう。

Visual C++のようなデバッガがついている開発環境があります。デバッガは、実行中のプログラムの様子を見ることができ、デバッグに手伝ってくれます。残念ながら、これは汎用的なやり方ではありません。すべての開発環境において存在しているわけでもないし、あるとしても使い方はそれぞれです。デバッガを使うと、どうしても個別の開発環境またはプラットフォームまたは両方に依存してしまうので、限定してプログラムを開発するならいいの(使うべき)ですが、プログラミング言語を勉強する人にはおすすめしません。

FCLKにはデバッガがついていません。興味がある人は、gdb を使うとよい。