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

C言語の話題いろいろ


久しぶりにNetNewsのfj.comp.lang.cというC言語のnews groupを覗いたら、投稿数が大爆発していて、びっくりしました。最近、環境依存の質問ばかりが多かったのでうんざりして見ていなかったのですけど、珍しく面白そうな話題が並んでいたので、はまってしまいました。
私、前から言っているように、プログラミング言語ならCが今のところ一番得意かな、という人間だったりするします(昔はFORTRANだったりする古い人間です…最近はFORTRANもすっかり忘れてしまいましたが)。最近はC言語に関する話題ももう散々出尽くしてしまったせいか、あまり目新しい議論が無くて、つまらない思いをしていたりしました。
本来なら議論に参加したいところではありますけど、いまNetNewsに投稿できる環境に無い(いや、無いことも無いけど、かなり面倒)のと、あれだけスレッドが爆発していると、さすがに時間が取れないなあ、と思うわけでして、こんなところに書いているわけだったりします ←いやまあ「ネタ見っけ」とこっちに書いている、ということだったりもしますけど。
とりあえず、あのnews groupを読んで、いろいろと有益な話があったので、ここで書いてみようか、などと思ったわけです。NetNews(またはfj.comp.lang.cというnews group)を見れない環境の方もいらっしゃると思いますので、一応あそこを読まなくても分かるような話をするつもりです。

あそこで一番爆発していたスレッドは、mallocしたら必ずfreeすべきか、という話題でした。あまりにも投稿が多すぎて私自身も半分も読んでいない(もう読みきれない)のですけど。
私自身が、初心者に教えるときにはずっと、とりあえず「mallocしたら、いらなくなったらfreeしてね」と言っていたのですけど、そういう硬直した教え方は弊害が多い、という意見が強かったですねえ。もちろん、mallocしたからといって、必ずfreeが必要というわけでも無いし(プログラム終了時など)、どういう場合にfreeが必要で、どういう場合にfreeが不要なのか、そのあたりを考えることなしに「mallocしたらfree」と決め付けるのはいかがなものか、というのも一理ありますね。
そもそも、どうなんでしょうね、初心者が安易にmallocとかやるプログラムを作ると、収拾がつかなくなるような気もするのですけど…ありがちなのが、関数の中でmallocしてfreeしないで抜けちゃうというのを延々繰り返して、というやつで、私自身は「対で使え」と言っておいた方がいいように思えるのですが、どうなんでしょう。まあ、どんなアルゴリズムのプログラムをよく作るか、というのにも依存する話かも知れません。
そう言えば、全然気にしたことも無かった(←ダメじゃん)のですけど、free関数の型ってvoidなんですね、あの議論を眺めていて初めて気づきました。これって実際に開放出来たかどうか分からない、ってことなんですよね。まあ「開放に失敗しました」と言われたところで、言われた方(freeの呼出し元)は困ってしまうだけかも知れませんけど…失敗したからと言われて、いったいどーしろってーの?
ところで、freeじゃなくて、fcloseなんかはどうなんでしょうね。こっちはエラーも帰ってきますし「fopenしたらfcloseしろ」でいいのかなあ。私はそう教えていますけど。

次に、ifは後ろに括弧「()」があるからCの関数だ、と主張している人がいて困っています、という話題です。
確かにこれ、初心者の中には勘違いしてしまう人がいますね。というか、プログラムの中で、どれが関数呼出しで、どれがそうじゃないのか、判別がつかない、という初心者は多いです。念のため言っておきますけど、if関数などというものはありません、「if文(if statement)」です。

    gf(1);  /* gfという関数の呼出し */
    hf(1);  /* hfという関数の呼出し */
    if(1);  /* ifという関数の呼出し…ではありません、if文です。意味無いけど */
    jf(1);  /* jfという関数の呼出し */

まあこれは極端な例で、3行目は関数呼出しじゃなくてif文なのですけど、このif文、結果的に何もやらないので、意味が無いですね、書いても書かなくても。
ではなぜ3行目だけ関数呼出しじゃないか、と言うと、「if」は予約語だから、というのに尽きるわけです。Cの予約語にどんなものがあるか、ということとか、予約語は識別子として使えない、ということとかは、Cのテキストを見れば、多分どこかに載っています。もし載っていないような本があったら、即座に捨てましょう :-)
でも、話は違いますけど、変なことを言い張る人ってのは、どこの世界にもいますよね。まあこれなんかは「ifは予約語だ」で終わりなのですけど、でもそれでも納得しない人はいるわけで。まあ、実害が無ければいいじゃん、という考えもありますし、この「if関数」問題は実害はあまり無いかも知れませんが、でもこういう人って、どこで実害が出るか分からないので怖いのも確かですね。

そういえば、この「if関数」問題の話の中で、構造体のメンバーを参照する演算子に「.」「->」の2つある必要は無いのではないか、という意見があって、なるほど、と思ってしまいました。
いやもちろん、Cの文法上、「.」演算子の前には構造体(共用体)型の式が来るわけですし、「->」演算子の前には「構造体へのポインタ」型の式が来るわけで、違う演算子なのですけど、別にこれらに同じ記号を使ったって混乱することはないよなあ、ということです。
Cの場合、結構、同じ記号だけど使い方によって意味が全く異なる、という例が多いので、だったらこれだって、同じ記号で違う意味を持たせたってかまわないのではないか、いったいなぜ分けたのだろう、というあたりに興味があったりします ←私も「同じ記号ではまずい」という例を考えてみたのですけど、思いつかなかった。
まあ、そういう文法なのだから、と言われてしまえばそれまでですけど。

「そういう文法なのだから」と言えば、これも話題になっていましたけど、やっぱり、いまいち納得いかないのがswitch文でしょうね。なんであんな文法になってしまっているんでしょう。まあ、あれはあれで便利なこともあるのですけど、「case」がラベルだ、というのが、どうにも…。
嫌なら「if 〜 else if 〜 else if 〜 … 〜 else」と、続けていけばいいだけの話ではありますけど、でももうちょっとなんとかならなかったのかなあ、などと思ったりもします。

あと、これもifにからんだ話ですけど、

    if (p != NULL) *p = 0;

のようなやつを、

    (p != NULL) && (*p = 0);

とかやるのは、いいか、悪いか、というような議論もありました(元の質問は違っていましたけど)。
これはどうなんでしょうね。Perlではよく見かける形ですけど、少なくとも私は、Cでは見たことがほとんど無いです。わざわざこういう書き方をする意味って何があるんでしょうか。
「どうして、この2つの文が同じ処理になるのか、理由を述べよ」なんて問題を出して、その人物の理解度を確かめる、なんてことには使えそうな気もしますけど :-)

[前へ] [次へ]

[Home] [戻る]


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