4

Zed Shaw のLearn C the Hard Wayから、演習 23 で、彼は Duff のデバイスについて話します。参考までに、ダフのデバイスは次のとおりです。

int duffs_device(char *from, char *to, int count)
{
    {
        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);
        }
    }

    return count;
 }

彼は読者に次のように求めます。

「このような任意の長さのデバイスを作成できる一連のマクロを作成します。たとえば、32 個の case ステートメントが必要で、すべてを書き出したくない場合はどうすればよいでしょうか?時間?"

これは本当に私を困惑させ、私は正しい方向に微調整する必要があると感じています. どんな助けでも大歓迎です!

4

1 に答える 1

6

このようなもの:

#define LAYDUFF(x, y) \
    case ((0 ## x ## y) + 1) : *to++ = *from++

#define SEVEN_AT_ONCE(x) \
    LAYDUFF(x,6); \
    LAYDUFF(x,5); \
    LAYDUFF(x,4); \
    LAYDUFF(x,3); \
    LAYDUFF(x,2); \
    LAYDUFF(x,1); \
    LAYDUFF(x,0)

#define EIGHT_AT_ONCE(x)    \
    LAYDUFF(x,7);           \
    SEVEN_AT_ONCE(x)

int duffs_device(char *from, char *to, int count)
{
    {
        int n = (count + 31) / 32;

        switch(count % 32) {
            case 0: do { *to++ = *from++;
                        SEVEN_AT_ONCE(3);                   
                        EIGHT_AT_ONCE(2);
                        EIGHT_AT_ONCE(1);
                        EIGHT_AT_ONCE(0);
                    } while(--n > 0);
        }
    }

    return count;
 }

に展開します

        case ((036) + 1) : *to++ = *from++; // = 31

                     ...

        case ((000) + 1) : *to++ = *from++; // = 1

アップデート:

または、最初のマクロを次のように書き換えることもできます。

        #define LAYDUFF(x, y) \
case (8 * x + y + 1) : *to++ = *from++

8 進数を使用しないことを除いて、基本的に同じです。

于 2013-12-16T02:44:07.760 に答える