What does the following code do and why would anyone write something like that?

Started by
7 comments, last by Zahlman 14 years ago
What does the following code do and why would anyone write something like that?

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

I have found this question over internet, calling send(p1,p2,15) will copy 15 ints from p2 to p1, but the first time case 7: triggers, how does this code repeats? case 0: do { ... is never called in this case and even then the loop runs back? the loop is even in-complete. what C++ feature am i missing which explains this?
Advertisement
Duff's device.
It is essentially a memcopy performed in chunks of 8 int sized pieces of data. It works because of the fallthrough capability of the switch statement. As to why someone would use it? Learning exercise about loop unrolling, but that is about it.
On some platforms, particularily very old platforms, and under the right conditions, it can be an efficient implementation. However, memcpy will be just as fast, if not faster, than anything you can create on your own 99% of the time. Don't try something like this unless: A) you know memcpy isn't working for you, and B) you've profiled it and proved it's better.
Quote:Original post by Antheus
Duff's device.


Thanks alot, that was helpfull, Although my point was not what its doing or how it works. I was more concerned about how the first time the loop is entered.

calling send(p1,p2,15); will call it like this initially.
void send (int *to, int * from, int count){	int n = 1;	switch (7)	{		// Not this part missed //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 );	}}


I was not able to understand how even this loop works since in this case its in-complete. Or lets say "do" is not executed so how does the compiler knows its a loop? only from "while"?
Read the 'reason it works' segment of the wiki link provided; it explains why it is allowed to work.

Effectively the compiler knows where the start of the loop is and the jump back to always happens.
In response to why anyone would write code like this if you use the Intel compiler you might need to be able to recognize unroll loops since it'll automatically insert some for you.
The Intel® Compilers can automatically unroll loops and insert branch-removing instructions.
[size="2"]Don't talk about writing games, don't write design docs, don't spend your time on web boards. Sit in your house write 20 games when you complete them you will either want to do it the rest of your life or not * Andre Lamothe
thanks guys, appriciated.
Remember, C++ is a compiled language, not interpreted. 'do' is not some kind of command that gets executed when an interpreter gets to that point; it tells the compiler to create code for the loop, and that loop is always created. Similarly, the case labels mark points where the control flow can jump when the 'switch' is evaluated. When the code runs, the switch causes the processor to jump into the middle of the loop; when it gets to the end, it checks the loop condition and jumps back to the beginning, because that's how the loop was written ahead of time by the compiler - i.e. that's what the code written at the end of the loop says to do.

This topic is closed to new replies.

Advertisement