// 通常是这样
void fastcopy(BYTE *pdest, BYTE *psrc, long count)
{
int n;
n = count / 8;
do
{
*pdest++ = *psrc++;
*pdest++ = *psrc++;
*pdest++ = *psrc++;
*pdest++ = *psrc++;
*pdest++ = *psrc++;
*pdest++ = *psrc++;
*pdest++ = *psrc++;
*pdest++ = *psrc++;
} while (--n > 0);
n = count % 8;
do { *pdest++ = *psrc++; } while (--n > 0);
}
// 然而这样更快,也更新颖
// 只是大家没有能够理解而已
void fastcopy(BYTE *pdest, BYTE *psrc, long count)
{
int n;
n = (count + 7) / 8;
switch (count % 8)
{
case 0: do { *pdest++ = *psrc++;
case 7: *pdest++ = *psrc++;
case 6: *pdest++ = *psrc++;
case 5: *pdest++ = *psrc++;
case 4: *pdest++ = *psrc++;
case 3: *pdest++ = *psrc++;
case 2: *pdest++ = *psrc++;
case 1: *pdest++ = *psrc++;
} while (--n > 0);
}
}
的确是一个很别致的代码,大家认真体会就是了。剩余数据的拷贝在第一次 do-while 循环中被执行,以后的循环中,每次循环都是拷贝了 8 个字节。switch 语句根据 count % 8 来转到相应位置,而转到的位置执行到 while 一句时,则是刚好将剩余数据拷贝完毕。这样做巧妙的减少了剩余数据拷贝时,所做的循环判断,因此其效率会比上面的算法快,然而这样的性能提升其实是微不足道的,而且这样的代码也不适合用于工程上。更加关键的是,这段代码的实际效率很大程度的依赖于编译器对 switch 语句的编译和优化处理。
所谓 Duff's Device 说的也就是这个意思。