質問: ch ){...} else{...} ``` そこで、switch文を使うのですが、、カッコも悪く効率も悪そうです。 ``` switch ( ch ){ case AAA: ... break; case AAB: ... break; ... case ZZZ: ... break; default: ... break; } ``` なぜなら、コンパイルの結果同じバイナリコードが生成されているとしたら 上から順に比較することになり最悪で26^3回の比較が必要になるからです。 26^3回がコンピュータにとってたいした数ではないかもしれませんが、極力多くしてみました。 それに始めて見たときにこのコードに対して、知的さを感じず快く思いませんでした。 そこで以下のようなコードを考えました。 ``` void (*name[])(void*)={ aaa, aab, ... , zzz}; namech; aaa(void* a){} aab(void* a){} ... zzz(void* a){} ``` これなら関数になるので抜け出す処理が記述されていても納得ですし。 caseがどんなに増えてもアクセスは定数時間かと思います。 巨大なswitch文が一人で居座るわけでなくなるので、ファイルの分割も行いやすくなります。 分割してコンパイルしていればそれ相応に恩恵を受けるかと思います。 ただ、ひとつ関数が増えるたびに変更する箇所がenumと配列,caseだけのswitchと比べたら手間になってしまっている気がします。 実際の現場ではどれが利用されて居るのでしょうか。 内心はif<3~5 switch<10 それ以上では、配列関数ポインタ又は、関数へのポインタの配列、もしくは関数の配列(実は名前を知らない)を利用したほうがよいと思うのですが、規則や効率など総合的に見てこういった書き方はどうなのでしょう。
回答: 本当に26^3通りの分岐を行いたいのでしょうか? 17576個のenumシンボルと17576個の分岐先関数を用意するのでしょうか? 私が過去にやったことがあるのは、JIS漢字コードからUnicodeへの変換やその逆変換を行うために、二分岐検索を用いたルックアップテーブルを作成したことがあるくらいです。 文字コードの変換の例でいうと、元の値は16ビット値でしたので、65536通りです。これを別の65536通りの値に変換するというものですが、このような用例では、処理を分岐したいわけでなく、値を変換したいだけなので、配列から値を取り出すとか、検索や演算で求めるだけで済むわけです。 実際の現場と仰っていますが、26^3個の分岐先の関数が、それぞれ関係のない別の処理を行うという状況はあまりありません、入力値である`ch`の値に応じて、ちょっとだけ違う似たような処理を行うのであれば、分岐先の関数を必要に応じてカテゴリー毎に何種類かに分けて、引数として`ch`を受け取る関数を用意すれば、大半の`ch`を一つの関数で受け持つことができるでしょう。 ここでいう`ch`が、ウィンドウメッセージやイベントやコマンドの番号の様なものだとして、17576種ものコマンドがあるかというと、実際の現場ではあまりないでしょう。仮にあるとしても、`ch`が数千種から数万種の値を取り得るという前提であれば、グループ番号とサブコマンド番号に分けるというのを検討してみます。例えば、上位8ビットをグループ番号、下位8ビットをサブコマンド番号とすることを考えます。符号無し8ビット整数であることが明らかならば、境界値チェックは必要なく、256個の配列を用いてジャンプテーブルを構成すればいいでしょう。一段目の分岐をジャンプテーブルで行い、二段目の分岐を`switch`で行うというもの、ありえない設計ではないと思います。 あとは、机上の議論ではなく、質問者が、具体的にどんな問題を解決したいかによって、どういう方法を採用するのが適しているかは変わってきます。