达夫设备--Duff's Device

来源:互联网 发布:中铁建物业怎么样知乎 编辑:程序博客网 时间:2024/05/20 06:25
今天遇到一个非常诡异的代码。不多说直接上代码。
void DuffDev(char *to, char *from, 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);}}void NormalCopy(char *to,char* from,int count){do{*to = *from++;}while (--count>0);}

我第一眼看到这个代码很懵。不知道是什么意思。switch case 和 do  while柔和在一起居然也不报错而且效率挺高。于是我在网上查询资料。才看到下面这段。

那段代码的主体还是do-while循环,但这个循环的入口点并不一定是在do那里,而是由这个switch语句根据n,把循环的 入口定在了几个case标号那里。也就是说,程序的执行流程是:程序一开始顺序执行,当它执行到了switch的时候,就会根据n的值,直接跳转到 case n那里(从此,这个swicth语句就再也没有用了)。程序继续顺序执行,再当它执行到while那里时,就会判断循环条件。若为真,则while循环开 始,程序跳转到do那里开始执行循环(这时候由于已经没有了switch,所以后面的标号就变成普通标号了,即在没有goto语句的情况下就可以忽略掉这 些标号了);为假,则退出循环,即程序中止。

duff’s device,是用Tom Duff的名字来命名的。很有名的一个东西,用来优化拷贝的,据说和Rob Pike此牛还有点儿关系~!不过注意,原始的duff’s device中的to可是不变的,因为它指向一个映射到内存的寄存器。

这是个很棒的迂回循环展开法, 由 Tom Duff 在 Lucasfilm 时所设计。它的 ``传统" 形态, 是用来复制多个字节: 
    register n = (count + 7) / 8;   /* count > 0 assumed */
    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);
    }

这里 count 个字节从 from 指向的数组复制到 to 指向的内存地址 (这是个内存映射的输出寄存器, 这也是为什么它没有被增加)。它把  swtich 语句和复制 8 个字节的循环交织在一起, 从而解决了剩余字节的处理问题 (当 count 不是 8 的倍数时)。相信不相信, 象这样的把  case 标志放在嵌套在 swtich 语句内的模块中是合法的。当他公布这个技巧给 C 的开发者和世界时, Duff 注意到 C 的 swtich  语法, 特别是 ``跌落" 行为, 一直是被争议的, 而 ``这段代码在争论中形成了某种论据, 但我不清楚是赞成还是反对"。


0 0
原创粉丝点击