1

これは以前にハッシュ化されたことを知っています。スイッチに関するすべての質問と回答を読んだことがあります。私の質問は、ダフのデバイスの構文や機能に関するものではありませんが、一般的なスイッチについては、たまたま質問をよく説明しています。

    {
    int n = (count + 7) / 8;

    switch(count % 8) {
        case 0: do { *to++ = *from++;
        case 7: *to++ = *from++;
        case 6: *to++ = *from++;
        case 5: *to++ = *from++;
        case 4: *to++ = *from++;
        case 3: *to++ = *from++;
        case 2: *to++ = *from++;
        case 1: *to++ = *from++;
        } while(--n > 0);
    }

n の値は反復ごとに減少します。また、緩やかなコンパイラ規則により、他のケースが do ループ内でジャンプできることも理解しています (奇妙ですが、理解しています)。

しかし、switch ステートメントは (count % 8) の関数であり、count の値に対して何も変更または作用していないため、最初に count が変更されてスイッチ内で異なるモジュロ剰余が生成されるのはなぜですか?

(count % 8) が最初のパスで 7 を生成すると仮定します。ケース 7 を処理した後: count の値は同じままであるため、(count % 8) の値は同じままである必要があるため、ケース 6: は true であってはならず、他のケースではなく、デフォルト n がなければデクリメントされるべきではありません。 do ループの次の繰り返しは、count の値を変更せずに開始する必要があります。そのため、ループは 0 まで終了し、count は決して変わらないように見えるため、すべてのパスでケース 7 のみが実行され、他のすべてのコードが無意味になります。

しかし、それが本当なら、ダフのデバイスは機能しません。なぜなら、count の値ごとに n の値の 8 回の繰り返しを生成するために明らかに int(n + 7)/8 に依存しており、(count % 8) と組み合わせると、count が実際にあることを意味するからです。デクリメントして、モジュロ剰余を 7 から 0 の間で減少させるループを生成します。

私の初心者の観点からは、これが機能するには、そのループのどこかに --count が必要なようです。したがって、私の結論は、スイッチの仕組みを理解していないということです。説明をいただければ幸いです。

4

1 に答える 1

0

さまざまなバージョンで少しテストを行った後、カウントは値を変更せず、n のみが値を変更していると安全に言えます。もちろん、これは、do:while 内で代入を 8 回連続して実行するだけで、スイッチがなくても元のコードがまったく同じように機能することを意味します。これは、純粋な難読化以外に、この場合、スイッチのポイントが何から始まるのか疑問に思います。 .

スイッチがどのように機能するかについては、各ケースにブレークを含めない限り、値に関係なくすべてのケースを実行することを除いて、スイッチが基本的に期待どおりに機能することをテストを通じて発見しました。count が変更されていないというさらなる証拠は、count の不変の値と相まって、Duff のコードにブレークがないことと相まって、切り替えが完全に無意味であったという主張をさらに裏付けています。

これはまったく同じ結果になります。

{
//integer division by 8 produces 8 iterations of the same value
int n = (count + 7) / 8; 

do {
    *to++ = *from++; //therefore since the loop will be 1/8th
    *to++ = *from++;
    *to++ = *from++; //the value of count you need to perform 
    *to++ = *from++;
    *to++ = *from++; //8 assignments per iteration of n
    *to++ = *from++;
    *to++ = *from++; //this produces the same result without
    *to++ = *from++;
    *to++ = *from++; //the switch
} while(--n > 0);

}   
于 2016-02-15T18:48:45.333 に答える