今更ながらC言語よもやま話


 筆者が会社でニュースソースにしているのは、インプレスが発行するメールマガジン、 INTERNET WatchPC Watch である。購読を始めた96年当時は(たぶん)唯一のまともなニュースメールだったが、現在では同趣旨のニュースメールは他にも存在するし、PC Watch はインプレスの Microsoft 提灯持ち体質が原因か、はっきりいって役立たず状態に成り下がっている。提灯持ちなら他にもソフトバンク、アスキー、日経BPの一部などいくらでもいるんだから、もうちょっと骨のある記事など載せようという心意気はないのか、と書いてみても、あるわけないのが分かっているから気合が入らない。予定調和である。

 Windows98 のユーザ登録を利用した Microsoft の不法ユーザデータ収集活動が発覚したときのコメントも、

ユーザーが“送りたくない”とした情報を、勝手に送ってしまうのは大きな問題だ。報道されてから慌てて情報を公開しているように見える対応も、決して褒めらたものではない。(1999-3-10)

だとよ。「決して褒めらたものではない」とは笑わせる。日本の政治家さんの「遺憾の意」とタメはれるね。そうしたインプレスの及び腰のコメントも「決して褒めらたものではない」ですな。こういう落としかたも予定調和だな。


 Linux カーネル2.2.0リリースも、司法省との裁判での予想外の(正直言って一審でも勝ってしまうだろうと思っていた)Microsoft の大誤算も黙殺状態の PC Watch はニュースメディアとして駄目だろう。スタパ齋藤とかいう低能の、「うぉー」「すげぇー」「!!」を多用したメーカー太鼓持記事を見かけるたび、朝から気合が抜けてしまう。仕方なく ZDnet 日本版、CNET 日本版を Web でチェックする毎日である。

 INTERNET Watch の方は、「デイリーやじうま」などいくらかひねりのあるコーナーがあるし、記事の対象がオープンな世界なだけまだ役に立っている。しかし、「デイリーやじうま」で取り上げる話題も前述のニュースソースからのの受け売りが多いから同じことなのだが。


 さて、以上は実はただの前振りである。長くなって申し訳ない。先日会社の同期とソフト開発について話していたとき、以前件の「デイリーやじうま」に載った微笑ましい話を思い出したのだ。

 TBSがインターネット関連のアルバイト募集をかけている。しかし、その応募資格がすごい。「CまたはPerlによるプログラミング経験がある方。日常会話レベルが必要」だそうだ。いくら言語だからって、そんなヤツいたら恐いぞ。

というもので(当然ながら現在はこの募集は TBS のサイトにはない)、思わずパソコンの前で吹き出してしまった。恐らくは最終的に文章を打ち込んだアルバイトさんが文脈を取り違えたのだろうか。文法的には問題なくてもその文章の使用される文脈を誤ると喜劇になってしまう好例である。でも Web 作成に携わるぐらいの人間ならコンピュータについて最低限(何をもって最低限と考えるかは置いといて)の知識は持っていそうなものだ。だれか門外漢が適当に書いた文章を分かっていて修正なしに打ち込んだのかもしれない。しかし、いくら高級言語でも日常会話となると難しい。悪ノリしてちょっと想像してみる。C言語での日常会話。僕が同僚に話し掛ける。

/* (~_~) あー、疲れた疲れた */
if(hungry(&you) == YES) goto lunch;     /* 腹へってたら昼飯に行こうよ */
else buy_snack(&me);    /* そうでなければ僕がなんか買ってくるよ */

 生真面目な同僚は苦々しい表情を隠さない。

/* (-_-#) お前なあ、納期は今週末だぞ! */
while(bug_is_fixed() == NG) {   /* バグがフィックスしない限りは駄目だ */
        sleep(10);      /* 10秒休息 */
        do_test();      /* テストを続ける */
}

 もう少し会話を現実レベルに近づけてみよう。以下は高級言語を日常会話に逆アセンブル(とは言わないか)した結果である。

「課長、どうしてここの仕様が変わったんですか? 聞いてませんよ」
「君のフラグも立った(=同意した)筈だ」
「それはありません。会話のソースコードを見て下さい」
「おい君、ここの else が上の二つの if のどっちにとっての else か分からないではないか。前々から分岐を大括弧でくくる手間を惜しむなと言っていただろう。それが嫌ならネストをきっちりやれ!」

 なーんてね。もしくはある日の飲み会にて。

「俺は課長の喋りかたがどうも気になってね。while 文で繰り返すからなんだな。俺はちゃんと for 文でないといつ喋りが終わるか見当が付かないと不安になるんだ」
「それにあの人タブ数が8だからさあ、全体に間延びしてるんだよなあ。4で十分じゃないか」
「そうそう、その上課長 if でも for でも while でも switch でも()との間にスペースを空けるよからさ、それすら冗長に思えちゃう。大体さあ、while 文を多用しすぎるんだよ。いついつ終わるか分かんない・・・」
「(いけない、こいつの愚痴が for(;;) に入ってしまった)」


 僕は大学で情報工学を専攻し、プログラミング言語として Pascal、C、Scheme、Prolog あたりを学んできた。当然メインはC言語である。しかし、意外にもそれ自体をじっくり学ぶ機会がなかった。そのため後までC言語の鬼門であるポインタをうやむやのまま過ごしてきた、というのは勿論言い訳である。K&Rの strcpy のソースのエレガントさ[註]を理解するまでに道草を食いすぎた。

 現在もC言語を使用しているが、ようやく C++ に手を伸ばす余裕が出来たところである。Windows アプリの一つぐらい作れないととは思うのだが、しかし MFC ってのはあんなに勝手にいろいろやってしまうケッタイな代物だとは思わなかった。オブジェクト指向言語ならばやはり Java の方に力を注がないといかんし、RUBY あたりにも唾を付けておきたい、と思いながら日々の雑事にかまけてしまう。


 しかし自分が書いたソースコードというのは後から見直すと非常に感慨深いものだ。ソースから自分の当時の記憶が蘇り、ノスタルジーにふける・・・などというのではなく、恐ろしく貧相なデータ構造に目眩をもよおし、センスのかけらもない無駄な変数配置に手直しする意欲すら萎える。Eric S. Raymond のオープンソースマニフェスト「伽藍とバザール」にも「賢いデータ構造と間抜けなコードのほうが、その逆よりずっとまし」という記述があるが、全くその通りだ。自分のことを棚に上げて言わせてもらえば、他人の書いたCのソースを追って通信プロトコルの実装を理解することが筆者にはよくあるが、プログラマのポリシーはしっかり感じるが、コードが先走りしていりためデータ構造が後追いで、コードの単なる穴埋めになっているところがはっきり読めることがあったりする。

 また前述の「伽藍とバザール」には「自分でもわかってないプログラムのバグをなおす責任をしょいこむなんて、おもしろくもないからね。」という記述があり、ESR 級のハッカーでもそれがあるのか、僕だけじゃなかったんだ、と親近感を持った。人のソースを見て、どこまでその他人の思考の具現化を追えるか、というのもその人のプログラマーとしての技量だろう。ある地点以上はブラックボックス(よーわからんが、この関数を通せば暗号化されてんだろ、みたいな)としてしか理解できないときは悔しいものだ。

 しかし、上の経験は他人のソースだけの話ではない。アルゴリズムのコアの部分をポインタ操作を駆使して一行に叩き込んだソースを見て、「確かに俺が書いたし、正しく動いてるみたいだが、このポインタ操作どういうことなんだ?」と訝しく思った経験がある。「Cプログラミングの秘訣」の「プログラミングに集中している時には一時的に脳の力が高まり、普段以上の精神活動を行うことができる」 という記述を実感し、いっぱしのソフトウェア技術者になった気になったりする。いい気なものだ。


 以前読んだ麻薬関係の書物の中で、コストもかからず禁断症状も耐性もない最高のドラッグとして「良心の刺激」が挙げられていた。中々面白い視点の転換だが、それに少し劣るとしても、プログラマーにとっての自分の書いたソースが正しく動作する様を見る瞬間というのも最高の刺激であり快楽である。あの瞬間の快感というのは、プログラムを書き始めた当初から現在に至るまで全く鈍る気配がない。

 しかし「正しく動作する」というのは飽くまで限定的な意味であり、バグのないプログラムなど存在しない。今日もテストに励み、半日悩まされたバグが何のことはない、if(x == 0) と書くべきところを if(x = 0) と書いていたためであることに気付いて脱力したりしながら僕はC言語と付き合っている。いずれは日常会話もCで行えるように・・・なれるわけはないか。


[註] K&Rとは B.W.カーニハン/D.M.リッチー著「The C programming language」(日本語訳は石田晴久訳で共立出版社株式会社から)のこと。筆者が所持する第二版(日本語版)には4通りの strcpy の実装例が記載されている。配列を使用した例が一つ。そしてポインタを使用した例が3つである。以下のように配列を使用すれば、初心者にもこの命令の意図は明らかだ。

void strcpy(char *s, char *t)
{
    int i;

    i = 0;
    while ((s[i] = t[i]) != '\0')
        i++;
}

しかし、ポインタを使ってもっとエレガントに表現可能だ。気取ってエレガントという言葉を使うのではない。数学・物理の問題がすっきりといった場合エレガントと表現するが、それをC言語で端的に表現したのが以下のソースである。

void strcpy(char *s, char *t)
{
    while(*s++ = *t++)
        ;
}

[前のコラム] [技術文書 Index] [TOPページ] [次のコラム]


初出公開: 1999年03月17日、 最終更新日: 2000年11月23日
Copyright © 1999, 2000 yomoyomo (E-mail: ymgrtq at yamdas dot org)