新・闘わないプログラマ No.322

C99あれこれ 〜コメント編〜


Cのコメントと言えば、“/*”と“*/”で囲まれた部分(途中に改行があってもよい)というのが、古くからある文法なのですが、これには「コメントを入れ子にすることができない」という大きな欠点があります。つまり、

    /* 〜(1)〜 /* 〜(2)〜 */ 〜(3)〜 */

というふうに記述した場合、コメントになるのは(1)と(2)の部分のみで、(3)の部分はコメントの外になってしまうわけです。なぜならば(1)の前にある“/*”に対応する“*/”は(2)の後ろにあるやつであって、決して(3)の後ろにあるやつではないからです。コメントの入れ子ができないためにこんなふうに解釈されてしまうわけです。
「なにもわざわざ、コメントの入れ子が必要なほど複雑な書き方しなければいいじゃないか」と思う人もいたりしますが、コメントを入れ子にしたい場合というのは現実にはよくあります。たとえば、

   for (i = 1; i <= 9; i++) {       /* 縦方向 */
       printf("%3d |", i);          /* 縦のインデックス印字 */
       for (j = 1; j <= 15; j++)    /* 横方向 */
           printf(" %3d", i*j);     /* 縦×横 印字 */
       printf("\n");                /* 改行 */
   }

なんていうソースの、3〜4行目をコメント化しようとして、

   for (i = 1; i <= 9; i++) {       /* 縦方向 */
       printf("%3d |", i);          /* 縦のインデックス印字 */
/*
       for (j = 1; j <= 15; j++)    /* 横方向 */
           printf(" %3d", i*j);     /* 縦×横 印字 */
*/
       printf("\n");                /* 改行 */
   }

ってなことやってもうまく行かないわけです。要するに、「すでにコメントが含まれている部分を、更にコメント化しようとしてもダメだ」ということになります。

そんな中、C99では新しいコメントの記述法ができました…というか、すでに大概の処理系で使えるようになっている、C++と同じコメント記法である“//”というやつですね。これはソース上の“//”のある部分(文字列リテラル内は除く)から、その行の終わり(改行文字がある)までをコメントとする、というものです。これに従って上記の例を書き直すと、

   for (i = 1; i <= 9; i++) {       /* 縦方向 */
       printf("%3d |", i);          /* 縦のインデックス印字 */
//     for (j = 1; j <= 15; j++)    /* 横方向 */
//         printf(" %3d", i*j);     /* 縦×横 印字 */
       printf("\n");                /* 改行 */
   }

となり、これは思ったとおりの結果になります。もちろん、すべてのコメントを“//”で書き換えて、

   for (i = 1; i <= 9; i++) {       // 縦方向
       printf("%3d |", i);          // 縦のインデックス印字
//     for (j = 1; j <= 15; j++)    // 横方向
//         printf(" %3d", i*j);     // 縦×横 印字
       printf("\n");                // 改行
   }

でも、全然問題ありません。
まあ、これはこれで「便利になりましたね」「やっと正式に規格化されましたか」というだけで、別にいちゃもんのつけどころは無いのですが…。

大昔の手続き型プログラミング言語と言うと、FORTRAN、BASIC、ALGOLなんてのが思い浮かびますが、このうちFORTRANとBASICはソース上で「行」というものに意味を持っています。1行に記述できる内容は決まっていて、それを(原則として)2行に分けて書くことも出来ませんし、また(特別の記述方法をしなければ)2行で書くべきことを1行で書くこともできません。それに対してALGOLは「行」に意味は無く、改行文字は空白と同じ扱いになりますので、どれだけの内容を1行に書くかはプログラマの方に任されています。
かなり以前、どこかで「FORTRANはソースを書くのにパンチカードを使ったことから行に意味を持つ文法になった」のに対して「ALGOLはソースを書くのに連続した紙テープを使ったので行に意味を持たない文法になった」というような話を聞いた記憶があるのですが…FORTRANについてはたぶんそうだと思うのですが、「ALGOLは紙テープ」というのはどうなんでしょう。ちょっと検索してみたのですが、それらしい情報は見つけられませんでした。どなたか情報をお持ちの方いらっしゃいましたら教えてください。
さてCは、記述方法に関して間接的にALGOLの影響を受けていますので、行に意味を持たないプログラミング言語ということになります…ただしプリプロセッサに関する文法を除いては。文法上「改行文字」は「空白類文字(white-space character)」ということになっているようで、空白文字と何ら違いが無いはずです。例外としては、すぐ上で述べたプリプロセッサと、あとは何かあったかな……そうだ、文字列リテラルの内部にはブランク文字は書けるのに改行文字を書けないですね。

ええと、要するに何が言いたいかと言いますと、「“//”で始まるコメントは改行文字で終わる」という文法で、行に意味を持たないはずのCにおいてなぜか改行文字を特別扱いしているなあ、と思っただけの話です。
いや、だから「こんな文法は許せん」とか言うつもりも無いのですが。“//”コメント、実際便利だし。

[前へ] [次へ]

[Home] [戻る]


mailto:lepton@amy.hi-ho.ne.jp