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 语句并且不想写出所有这些语句怎么办?您可以创建一个包含 8 个的宏吗?一次?”

这真的难倒我,我觉得我只需要朝着正确的方向轻推。任何帮助将不胜感激!

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++

这基本相同,只是它不使用八进制数。

于 2013-12-16T02:44:07.760 回答