void* memorycopy (void *des, const void *src, size_t count)
{
size_t n = (count + 7) / 8;
char* destination = (char *) des;
char* source = (char *) src;
switch (count % 8)
{
case 0: do{ *destination++ = *source++;
case 7: *destination++ = *source++;
case 6: *destination++ = *source++;
case 5: *destination++ = *source++;
case 4: *destination++ = *source++;
case 3: *destination++ = *source++;
case 2: *destination++ = *source++;
case 1: *destination++ = *source++;
} while (--n > 0);
}
return des;
}
void tworegistervarswap (int *x, int *y)
{
if (x != y)
{
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}
}
int bigintegeraverage (int x, int y)
{
return (x & y) + ((x ^ y) >> 1);
}
答案 0 :(得分:3)
switch
的恐怖是Duff's device(创造性展开的循环,但除此之外它只是将来源复制到目的地)。
tworegisterswap
使用按位XOR交换x
和y
指向的值。
bigintegeraverage
是一种偷偷摸摸的方式,以潜在的非便携方式获得两个整数的平均值,但没有溢出的可能性。 (有关详细信息,请参阅Aggregate Magic Algorithms。)
答案 1 :(得分:1)
它被称为Duff的设备。它使用switch
语句在C中实现状态机。在这种特殊情况下,它每8次memcopy迭代执行一个分支。
请阅读此内容以获取更多信息:http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
第二个函数交换两个整数。
第三个只计算两个数的平均值,因为sum可以写为
a + b = (a ^ b) + ((a & b) << 1); // the AND here represents carry
并使用((a ^ b) >> 1) + (a & b)
代替(a + b >> 1)
,我们可以避免可能的溢出。
答案 2 :(得分:1)
设备的要点是直接在C中表示一般循环展开。已经发布说“只使用memcpy”的人已经错过了这一点,那些使用各种依赖于机器的memcpy实现作为支持批评它的人也是如此。实际上,消息中的示例不能作为memcpy实现,任何计算机也不可能具有实现它的类似memcpy的习惯用法。 more
答案 3 :(得分:0)
这实际上是3个功能。
memorycopy()
......好吧,其他人可以解决这个问题:P
tworegistervarswap()
似乎指向了两个int
s,如果它们不匹配,那么它会对它们进行一些调整(XOR)。它在不使用临时变量的情况下交换值。
bigintegeraverage()
需要两个int
并根据它们返回均值(感谢Steve Jessop),同时使用位摆弄(AND,XOR和RIGHT SHIFT)。