jos*_*osh 3 c c++ cpu-registers
可能重复:
代码有什么作用?
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);
}
}
Run Code Online (Sandbox Code Playgroud)
以上是有效的C代码吗?如果是这样,它想要实现什么,为什么有人会像上面这样做?
它被称为Duff的设备,您可以在维基百科上阅读它.
它解决了展开循环的一个问题:可能需要非整数次传递.一种方法是在主循环之外处理这个问题,但是使用Duff的设备更有效,它使用非常快速的跳转表并避免额外的循环开销来处理奇数个操作.
在您的示例中,这是一个内存副本,请与天真的版本进行比较:
void memcpy(char* dst, char* src, size_t count)
{
begin:
if (count-- == 0) return;
*(dst++) = *(src++);
goto begin;
}
Run Code Online (Sandbox Code Playgroud)
要复制15个字节,请执行以下操作:
测试计数,复制,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,复制,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,副本,循环,测试计数,复制,循环,测试计数
注意必须完成"测试计数"和"循环"操作的次数.
使用你展示的duff版本,它更简单:
基于计数,复制,复制,复制,复制,复制,副本,副本,测试计数,循环,副本,副本,副本,副本,副本,副本,副本,副本,测试计数跳
这节省了一半以上的步骤
这是有效的.这是一个非常老派的循环展开.
基本上,不是检查被复制的每个字符的计数以确定何时停止,而只需要检查ceil(n/8)次.
register关键字只是一个编译器提示,表明编译器试图将该值保存在寄存器中,而不是将其随机存入和移出主存储器.
显然,这样的东西不再是必要的(memcpy()很可能在你编写的任何机器上实现非常快速的实现)但这样的技巧实际上提供了相当不错的性能获胜.