Home日記コラム書評HintsLinks自己紹介
 

フィンローダのあっぱれご意見番 第82回「構造上の問題」

「フィンローダのあっぱれご意見番」一覧 | 次のをみる →

前回紹介した通り、最近はVAIO PCG-505RXを持ち歩いて使っている。 まだ買って間もないような気がするが、 既に生産終了して後継機が出ているというのが恐ろしい。

 

※ 昔のVAIO ノートは生産数が少なかったようだ。

ともあれ、これは予想以上によいpcである。特に薄さがよい。 これでTP535を持ち歩いていた頃と、かばんの使い方が変わった。 今まで入らなかったような薄いかばんで外出することが可能になったわけだ。 重さも重要だが、厚さも結構重要なファクターなのだ。

実は、最初にVAIOの505シリーズが発表されたときに、「ろ」のキーと右シフトキーの間に 上カーソルキー「↑」が配置されていることに、 かなりの抵抗を感じて、購入を躊躇した。 シフトキーは、特に文章入力中に頻繁に使う。 この時に間違ってカーソルキーを押したら、 カーソルの位置が変化して、その結果、意図しない所に文字が入ることになる。 これを修正する手間が、文書作成の効率を著しく低下させるだろう。

  

このキー配置では、 かなりの頻度で誤打鍵が発生するのではないか、 また、シフトキーを確実にタイプしようとして、 指がかなり緊張し、負担がかかるのではないか、と予想したのである。 ところが、実際使ってみると意外なことにそれほど致命的ではないのだ。 あまり間違えないのである。 「あまり」というのは、要するに間違うことは実際にあるわけだ。 ただ、思ったよりは、ずっと頻度が少ない。 つまり、シフトキーをあまり間違えずに押すことができるのだ。 理屈と実際が違うという面白い事例である。 ただし、指が多少緊張しているというのも事実で、 右手小指が少し疲れるような感じは残るような気がする。

 

※ むしろちょっと違和感が残ったのは、キーピッチである。 標準のキーピッチよりも、微妙に狭いのだ。

§

キー配置の躊躇にも関わらず505RXを購入した理由の一つが、表示能力である。 505RXは、1024×768ドットの表示が可能である。 最初の1~2週間は表示される文字が少し小さく感じたが、 最近は慣れてしまって、もう少し小さくても読めそうな気がしている。 液晶の場合、字が小さくなっても、 CRTのようにフォーカスが甘くて見にくいという状況にはならない。 クリアな表示のままである。 むしろ、字が小さすぎて見えないとか、そういう心配はあるはずだが、 505RXの程度の解像度でも、まだ文庫本の字よりは少し大きい程度だから、 実用的な大きさの限界までにはまだ多少の余裕があると思う。

§

  

昔はCのプログラムを書くとき、 関数の長さを25行以内にするのがよい、 という有名な珍説があった。 理由は、画面に一度に表示できるのが25行だから。 一度に見渡せないとミスの原因になるだろう。 それはわかる。しかし、あらゆる処理を25行以内に書けるのだろうか。 論理的には無理ではない。例えば、どんどん関数に分ければよい。 しかし、処理を細切れにしすぎると、 どの関数が何の処理であるかを理解するのが難しくなる。 うまく設計しないと、関数相互の依存性も増える。 関数read_one_lineの前に関数reset_textを呼ばなければならない、 というような束縛条件を忘れてバグが発生するかもしれない。

 

※ 昔のpcは、640x400ドットの表示能力で、 8x16ドットの文字は横に80字(全角40字)、 縦に25行しか表示できなかった。

ところで、最近のpcを使う場合、画面にどの程度の文字を表示できるだろうか。 大雑把だが、 768を16で割ったら48である。 20で割っても38.4。じゃあこの程度までの行数は問題ないかというと、 そういう話じゃないような気もする。 仮に、1画面に1000行表示できるディスプレイがあったとして、 それを使ったら1000行の関数を使ってもいいかというと無茶な話である。 数百行も集中して読めば、 その後は最初の処理を徐々に忘れて行くものである。 測定したわけではないが、私の場合、 感触としては200~300行というのが最高に集中した状態を持続できる限界だと思う。 記憶力は個人の能力差に大きく依存することにも留意が必要である。 一概に何行までならok、ということは言えないはずだ。とはいっても大雑把な目安は必要だが。

  

とりあえず、VAIOに限らず、 モバイルpcとしてプログラマーの立場で期待したいスペックとしては、 あと少し細かくてもいいから、VAIOの大きさの本体で、 1600×1200程度の解像度。これだけあればどこでも仕事ができそうで、 それってもしかして地獄かもしれませんが、まあ面白い世界になるのではないか。

 

※ 今使っている VAIO BX は 1400 x 1050 の画面表示能力がある。

§

  

少し前の回で、一度もループしないforループを紹介した。 List 1のように、必ずbreakしてしまうので、最初に戻らないのである。

 

第79回:空白の理由 (1)

---- List 1 ----

    for (;;) {
        /* 処理 */
        break;
    }

---- List 1 end ----

わざわざこのように書く理由は、gotoを使わないでブロックの中から外に出たいからである。 つまり、gotoを使えばList 2のように書くところである。 List 2は、わざとブロックを使っているが、ブロックで囲む必然性はない。 おそらく、このように書く場合はブロックにしないことが殆どだと思う。 ただ、こうやって書いてみると、 意図的にブロックにした方が何をやっているのか分かりやすいような気もしてきた。

---- List 2 ----

    {
        /* 処理 */
        goto block_end;
    }

block_end:

---- List 2 end ----

さて、話はこれで済む予定だったのだが、 ニフティサーブのFPROGORGでこの話題が出ると、 do-whileを使った方がよいのではないか、という意見が出た。 List 3のようになる。この書き方は、 1度もループしないということがwhile (0)によって明確であるという利点がある。

---- List 3 ----

    do {
        /* 処理 */
    } while (0);

---- List 3 end ----

do-while (0) というのは、 C言語では、マルチステートメントをマクロにしたい時に使うテクニックとして有名だ。 comp.lang.c FAQの "What's the best way to write a multi-statement macro? " という項にはList 4が紹介されている。
(http://www.eskimo.com/~scs/C-faq/q10.4.html)

---- List 4 ----

        #define MACRO(arg1, arg2) do {  \
                /* declarations */      \
                stmt1;                  \
                stmt2;                  \
                /* ... */               \
                } while(0)      /* (no trailing ; ) */

---- List 4 end ----

もちろん、statementはいくら書いても構わないのである。 些細なことだがstmt1;のようにセミコロンが付いているのは何でしょうか、 statement即ち「文」なんだから、もし「文;」というのなら 文にセミコロン付けてどうする、という話になって ちょっと気味が悪いのだが、 じゃあ「stmt1;」ってのは「文1;」なのか。 いやいや、stmt1というのが式(expression)だってことだね、多分。それでつじつまが合う。以上。

とりあえず余談はさておき、 もちろん文はいくら書いても構わなくて、 最後の while (0)に「;」が付いていないのがミソである。 例えばこのテクニックでマクロ macro(i, j) を定義したら、 コードの中で使う時には macro(i, j); のように書きたくなる。 つまり、セミコロンはマクロ定義ではなくマクロを使う時に書かれることになる。 だからマクロ定義には出てこない。 単にブロックで囲むだけではダメな理由は、if-elseの中に使われた場合を考えれば分かる。 クイズとしては手頃な難易度なので、考えてみてください。

しかし、do-whileといえば、 先入観として「終了条件が最後に出てくるループ」というものがないだろうか。 あくまでループはループ、一度もループしないとしても、 それはループの一種、というようなイメージが頭にある限り、 何か誤解が生まれる余地はありそうだ。 そこで、さらに姑息な方法としてはswitchを使う方法もある。

---- List 5 ----

    switch (0) {
    default:
        /* 処理 */
        break;
    }

---- List 5 end ----

別に0でなくても何でもいいのだが、 とりあえずcase 0: で受けるよりはdefaultの方がよさそうだ。理由はわからないが。 defaultしかないというのが異様だが、とにかく どこでbreakしてもswitchの外に飛び出すのである。 もちろん、中にさらにforとかwhileのループがある場合は話が別なのは言うまでもない。 この書き方だと、 forループの場合につきまとう「もしかしてcontinueがあるのでは」という疑心暗鬼からも逃れることができる。

§

というわけで、書き方が結構あるものだと感心している場合ではない。 根本的な問題がありそうだ。 そもそも、プログラムをこんな構造にしてもよいのだろうか。 と言われても、現にそうなっているのだから仕方ない、という考え方に対抗するのは難しい。 確かにどこからでも飛び込んでくるプログラムよりは、 どこからでも飛び出すプログラムの方がまだマシである。 ブロックを途中で抜け出すというのは、 全体の処理をそれほど乱雑にする構造ではなさそうだ。 例外処理で書けばすっきりするのかもしれないが、 実際にプログラムを動かした時にどこからどこへ処理が移っているのか考えるのも頭痛の種になりそうだ。 しかしいまいち釈然としない感じがするのも事実である。

とりあえず、実際に使ってみてうまく行くのなら、 それも選択肢の一つとして考えるというのも現実的な解法かもしれない。

  

(C MAGAZINE 1999年4月号掲載)
内容は雑誌に掲載されたものと異なることがあります。

修正情報:
2006-03-15 裏ページに転載。

(C) Phinloda 1999-2006, All rights reserved.