为Duff的设备写一个宏

时间:2013-12-16 02:12:32

标签: c c-preprocessor duffs-device

来自Zed Shaw,艰难地学习C ,在练习23中,他谈到了Duff的设备。这是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个?“

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

1 个答案:

答案 0 :(得分: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++

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