这是有效的 C 代码吗?

发布于 2024-09-12 22:49:25 字数 673 浏览 2 评论 0原文

可能的重复:
这段代码的作用是什么?

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

上面的 C 代码是有效的吗?如果是这样,它想要实现什么目的以及为什么有人会做上述事情?

Possible Duplicate:
What does the code do?

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

Is the above valid C code? If so, what is it trying to achieve and why would anyone do something like the above?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

热鲨 2024-09-19 22:49:25

它被称为达夫的设备,您可以在维基百科。

它解决了展开循环的一个问题:可能需要非整数的传递次数。一种方法是在主循环之外处理这个问题,但使用 Duff 的设备更有效,该设备使用非常快的跳转表,并避免处理奇数操作的额外循环开销。

在您的示例中,这是一个内存副本,请与原始版本进行比较:

void memcpy(char* dst, char* src, size_t count)
{
   begin:
     if (count-- == 0) return;
     *(dst++) = *(src++);
     goto begin;
}

要复制 15 个字节,将执行以下操作:

测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试计数,
复制,
环形,
测试次数

请注意必须执行“测试计数”和“循环”操作的次数。

使用您展示的达夫版本,它要简单得多:

根据计数跳转,
复制,
复制,
复制,
复制,
复制,
复制,
复制,
测试计数,
环形,
复制,
复制,
复制,
复制,
复制,
复制,
复制,
复制,
测试次数

可节省一半以上的步骤

It's called Duff's device and you can read about it on wikipedia.

It takes care of one problem with an unrolled loop: there could be a non-integer number of passes needed. One method is to deal with this outside the main loop, but it's more efficient to use Duff's device which uses a very fast jump table and avoids extra looping overhead dealing with the odd number of operations.

In your example, which is a memory copy, please compare to the naive version:

void memcpy(char* dst, char* src, size_t count)
{
   begin:
     if (count-- == 0) return;
     *(dst++) = *(src++);
     goto begin;
}

To copy 15 bytes, this does the following:

test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count,
copy,
loop,
test count

Note how many times the "test count" and "loop" operations must be done.

Using duff's version which you showed, it is much simpler:

jump based on count,
copy,
copy,
copy,
copy,
copy,
copy,
copy,
test count,
loop,
copy,
copy,
copy,
copy,
copy,
copy,
copy,
copy,
test count

which saves over half the steps

过期情话 2024-09-19 22:49:25

这是有效的。这是一个非常老式的循环展开。

基本上,它不必检查正在复制的每个字符的计数来确定何时停止,而只需检查 ceil(n/8) 次。

register 关键字只是一个编译器提示,建议编译器尝试将该值保留在寄存器中,而不是将其混入或混出主内存。

显然,这样的东西不再是真正必要的了(memcpy() 可能在您正在编码的任何机器上都有一个非常快的实现),但是这样的技巧实际上可以提供相当不错的性能胜利。

It's valid. It's a very old-school loop unroll.

Basically, instead of checking the count for every character that's being copied to determine when to stop, it only has to check ceil(n/8) times.

The register keyword is just a compiler hint to suggest that the compiler try to keep that value in a register instead of shuffling it in and out of main memory.

Obviously stuff like this isn't really necessary anymore (memcpy() is likely to have a very fast implementation on whatever machine you're coding for) but tricks like this used to actually provide pretty decent performance wins.

離殇 2024-09-19 22:49:25

指向 维基百科上的达夫设备的强制链接。

Obligatory link to Duff's Device on Wikipedia.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文