2

コンパイラー作成、特に最適化に関する知識とスキルを広げたいと思っています。文字列型の case 式を使用した case-statement で利用可能な最適化を知りたいです。たとえば、Object Pascal では次のようになります。

ReadLn(s);
case s of
  'abc','def': ...;
  'xyz'      : ...;
  otherwise    ...;
end;

Free Pascal では、これは AnsiCompareText の後続の呼び出しに変換されます。他の言語の実装はどうですか? 少なくとも PHP、Nimrod、および Octave がこれをサポートしていることは知っています。

4

2 に答える 2

0

C では、char 配列 (文字列) に相当する「ケース」はありませんが、ビット シフト マクロとスイッチ ケースを使用してある程度実現できます。

#define FIVE_CHARS(c1,c2,c3,c4,c5)  (((((((((c5)<<7)|(c4))<<6)|(c3))<<6)|(c2))<<6)|(c1))

while (argc-->0){
  switch ( FIVE_CHARS(argv[argc][0],argv[argc][1],argv[argc][2],argv[argc][3],argv[argc][4]) ){
     case FIVE_CHARS('-','h','e','l','p')  :
     case FIVE_CHARS('-','-','h','e','l')   :
     case FIVE_CHARS('-','h','\0','\0','\0')   :
     case FIVE_CHARS('-','?','\0','\0','\0')   :
       usage();
     break;
     case FIVE_CHARS('-','a','r','g','1')   :
       setflag1();
     break;
     default:
       assert("Argument not supported");
  }
}

コンパイラは、これを一連の if として少数の比較でコンパイルするか、多数のジャンプ テーブルとしてコンパイルします。ほとんどのビット シフト (case ステートメント内のもの) は実行時ではなくコンパイル時に行われ、残りのビット シフト操作 (switch 内のもの) は比較的安価であり、 1回の比較で1回だけ必要です(基本的に、最も一般的なパスを最初に配置する必要がなくなります)... 5文字が一致する場合は、珍しい文字に追加のスイッチケースを追加するか、単に strcmp() を使用できます。 .. ただし、 if strcmp() {} else if strcmp() {} else の巨大なネストされたツリーよりも、いくつかのケースでのみ strcmp が必要な方がよいでしょう ...

于 2012-04-12T04:28:21.790 に答える
0

アプリケーション開発者として、比較の数を制限するために、実行される可能性が最も高いケースを最初に配置したいと考えています。残念ながら、コンパイラの観点からは、実行時までそれがわかりません。

私が独自のコンパイラを作成していて、上記のような case ステートメントに遭遇した場合、比較をソートしてバイナリ検索を実行して、どのパスを使用するかを決定するでしょう。これにより、最悪のシナリオが少し改善されることが期待されます。

于 2011-02-04T17:01:59.320 に答える