什么是达夫设备(Duff's Device)

本文深入探讨了达夫设备这一C语言编程技巧,介绍了其工作原理和应用实例。达夫设备利用switch语句巧妙地控制循环的展开过程,有效减少了循环测试次数,提高了代码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在看《你必须知道的496个C语言问题》一书中,提到”达夫设备”这个东西,主要是下面的代码:

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);
}

这是个很棒的迂回循环展开法, 由 Tom Duff 在 Lucasfilm 时所设计。它的“传统”形态, 是用来复制多个字节。

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

函数包含一个switch语句,它的case语句同时位于一个while循环体内(有一个case语句在外面)。switch内的表达式计算被八除的余数。执行开始于while循环内的哪个位置由这个余数决定,最终循环退出,(没有break)。Duff’s Device这样就简单漂亮地解决了边界条件的问题。顺便提一下,为什么”case 0”标记在循环外面呢?这样不是打破了对称的美观吗?这样做的唯一理由是为了处理空序列。当余数为零,”case 0”内就需要执行一个多余的测试来判断空序列的可能性。总之,这是个很酷的算法。

达夫设备是一个加速循环语句的C编码技巧。其基本思想是–减少循环测试的执行次数。

如果在一个for循环中,其中操作执行得如果足够快(比如说,一个赋值)——那么测试循环条件占用了循环所用时间的很大部分。循环应该被部分解开,这样数个操作一次完成,测试操作也做的较少。其实,是通过switch语句将要进行的连续循环操作的次数进行了预判(根据擦case语句的位置)然后依次执行,而不必每次都去进行测试条件。

在这里Duff’s Device是个新颖的,有创造力的解决方案。这里有一个使用该模型的一个实例:快速拷贝和填充。

Duff’s Device对效率的负面影响可能来自于代码膨胀(一些处理器更善于处理紧凑的循环而不是大的循环)和特别的结构。优化器被做成当遇一些更加技巧性的结构时可能会不知所措从而生成比较保守的代码。

其实达夫设备是使用switch语句来控制进入循环的位置。

下面的程序是简单验证达夫设备的执行:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    int n;

    if(argc < 2)
    {
        printf("Two arguments at least!\r\n");
        return -1;
    }

    n = atoi(argv[1]);

    switch(n)
    {
        do {
    case 0: 
        printf("%d ",0);

    case 1: 
        printf("%d ",1);

    case 2: 
        printf("%d ",2);

    case 3: 
        printf("%d ",3);

    case 4: 
        printf("%d ",4);

        }while(--n>0);
    }

    return 0;
}

运行结果演示:
这里写图片描述

原文出处:http://www.cnblogs.com/xkfz007/archive/2012/03/27/2420163.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值