Can anyone figure out what this method (in C) is doing? Trying to understand this for an assignment
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 (coun开发者_Go百科t % 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);
}
The horror with switch
is Duff's device (a creatively unrolled loop, but otherwise it just copies source to destination).
tworegisterswap
swaps the values pointed to by x
and y
using bitwise XOR.
bigintegeraverage
is a sneaky way to get the average of two integers in a potentially non-portable manner but without the possibility of overflow. (See Aggregate Magic Algorithms for details.)
It's called Duff's device. It uses switch
statement to implement state machines in C. In this particular case it performs one branch per 8 iterations of memcopy.
Read this for additional info: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
The second function swaps two integers.
The third just computes the average of two numbers, because sum can be written as
a + b = (a ^ b) + ((a & b) << 1); // the AND here represents carry
and by using ((a ^ b) >> 1) + (a & b)
instead of (a + b >> 1)
we can avoid possible overflows.
See Tom Duff on Duff's Device:
The point of the device is to express general loop unrolling directly in C. People who have posted saying `just use memcpy' have missed the point, as have those who have criticized it using various machine-dependent memcpy implementations as support. In fact, the example in the message is not implementable as memcpy, nor is any computer likely to have an memcpy-like idiom that implements it. more
That is actually 3 functions.
memorycopy()
... well, someone else can figure that one out :P
tworegistervarswap()
seems to take pointers to two int
s, and if they don't already match, then it does some bit fiddling with them (XOR). It swaps the values without using a temporary variable.
bigintegeraverage()
takes two int
s and returns the mean (thanks Steve Jessop) based on them, using bit fiddling as well (AND, XOR and RIGHT SHIFT).
精彩评论