why Its a Valid Code

P

Pallav singh

In the Given below code Does case const-expression: do not have anny
effect on do ...while(); loop

Thanks
Pallav Singh

#include<stdio.h>
#include<stdlib.h>


int main()
{

char to1[] ="Pallav";
char from1[] = "Puneet";

char *to = to1;
char *from = from1;
int count = 21;

printf("Value in to is %s \n\n",to);
printf("Value in from is %s \n\n",from);

register n = (count + 7) / 8; /* count > 0 assumed */

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);
}

printf("Value in to is %s \n\n",to);
return 0;


}
 
B

Barry

Pallav said:
In the Given below code Does case const-expression: do not have anny
effect on do ...while(); loop

Thanks
Pallav Singh

#include<stdio.h>
#include<stdlib.h>


int main()
{

char to1[] ="Pallav";
char from1[] = "Puneet";

char *to = to1;
char *from = from1;
int count = 21;

printf("Value in to is %s \n\n",to);
printf("Value in from is %s \n\n",from);

register n = (count + 7) / 8; /* count > 0 assumed */

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);
}

printf("Value in to is %s \n\n",to);
return 0;


}


http://c-faq.com/misc/duff.html
 
D

Daniel T.

Pallav singh said:
In the Given below code Does case const-expression: do not have anny
effect on do ...while(); loop

I suggest you try to (a) modify the code so it can compile in C++, (b)
modify the code so it actually does what you think it should do, then
(c) step through the code in your debugger and see how it does it.

BTW, this is a classic example of using unstructured code as a special
case optimization, don't do this sort of thing by default.

(Unstructured code is any code where there is a jump into or out of the
middle of a loop or conditional.)
#include<stdio.h>
#include<stdlib.h>


int main()
{

char to1[] ="Pallav";
char from1[] = "Puneet";

char *to = to1;
char *from = from1;
int count = 21;

printf("Value in to is %s \n\n",to);
printf("Value in from is %s \n\n",from);

register n = (count + 7) / 8; /* count > 0 assumed */

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);
}

printf("Value in to is %s \n\n",to);
return 0;


}
 
J

Joe Greer

#include<stdio.h>
#include<stdlib.h>


int main()
{

char to1[] ="Pallav";
char from1[] = "Puneet";

char *to = to1;
char *from = from1;
int count = 21;

printf("Value in to is %s \n\n",to);
printf("Value in from is %s \n\n",from);

register n = (count + 7) / 8; /* count > 0 assumed */

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);
}

printf("Value in to is %s \n\n",to);
return 0;


}

A couple of notes:

1) The pointer 'from' is pointing out into the middle of nowhere so the
value assigned into '*to' is semi random.

2) The above loop boils down to:
int m = count % 8;
if (m == 0) m = 8;

from += m + (n-1) *8;
*to = *(from -1);

I would think this would be a bit more efficient, if just as odd as
the above. You still have the out of bound memory access problem.

joe
 
J

James Kanze

(e-mail address removed):
#include<stdio.h>
#include<stdlib.h>
int main()
{
char to1[] ="Pallav";
char from1[] = "Puneet";
char *to = to1;
char *from = from1;
int count = 21;
printf("Value in to is %s \n\n",to);
printf("Value in from is %s \n\n",from);
register n = (count + 7) / 8; /* count > 0 assumed */
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);
}
printf("Value in to is %s \n\n",to);
return 0;
}
A couple of notes:
1) The pointer 'from' is pointing out into the middle of nowhere so the
value assigned into '*to' is semi random.
2) The above loop boils down to:
int m = count % 8;
if (m == 0) m = 8;
from += m + (n-1) *8;
*to = *(from -1);
I would think this would be a bit more efficient, if just as odd as
the above. You still have the out of bound memory access problem.

The code outside the switch is completely wrong, of course, but
the switch itself is a very literal copy of Duff's device (where
to pointed to what would today be a char volatile*). There are
lots of possible variants, of course. The whole point of the
exercise is that switch, in C++, really is a calculated goto
with special labels. And although this example doesn't show it,
there's also no requirement that the controled statement in a
switch be a compound statement. Something like:

switch ( count % 8 )
while ( count > 0 ) {
case 0 :
*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 ++ ;
count -= 8 ;
}

would also be perfectly legal.

Another variant I've seen:

switch ( *p ) {
// ...
case '.' :
if ( isdigit( *(p + 1) ) ) {
case '0' : case '1' : case '2' : case '3' :
case '4' : case '5' : case '6' : case '7' :
case '8' : case '9' :
scanFloatingPointConstant( p ) ;
} else {
case '~' : case '!' : case '%' : case '^' :
// ...
scanPunctuation( p ) ;
}
break ;
// ...
}

There's no rule that all of the case labels have to be at the
same level of nesting either.
 
J

Joe Greer

The code outside the switch is completely wrong, of course, but
the switch itself is a very literal copy of Duff's device (where
to pointed to what would today be a char volatile*). There are
lots of possible variants, of course. The whole point of the
exercise is that switch, in C++, really is a calculated goto
with special labels. And although this example doesn't show it,
there's also no requirement that the controled statement in a
switch be a compound statement. Something like:

switch ( count % 8 )
while ( count > 0 ) {
case 0 :
*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 ++ ;
count -= 8 ;
}

would also be perfectly legal.

Another variant I've seen:

switch ( *p ) {
// ...
case '.' :
if ( isdigit( *(p + 1) ) ) {
case '0' : case '1' : case '2' : case '3' :
case '4' : case '5' : case '6' : case '7' :
case '8' : case '9' :
scanFloatingPointConstant( p ) ;
} else {
case '~' : case '!' : case '%' : case '^' :
// ...
scanPunctuation( p ) ;
}
break ;
// ...
}

There's no rule that all of the case labels have to be at the
same level of nesting either.

I would never say there is no use for such code, but I would want to be very sure that any code like
that was truly required. You can easily run into traps where the code is actually slower because you
are actually doing more work than just a straight forward calculation. Not to mention that any poor
maintenance programmer who had to try to fix it would have a few hair pulling sessions before he
figured it out (in my experience any way). Anyway, I was responding to the specific code, not the
idea.

joe
 
J

James Kanze

(e-mail address removed):

[...]
I would never say there is no use for such code, but I would
want to be very sure that any code like that was truly
required.

I didn't say I approved of it, jsut that I'd seen it:).
You can easily run into traps where the code is
actually slower because you are actually doing more work than
just a straight forward calculation. Not to mention that any
poor maintenance programmer who had to try to fix it would
have a few hair pulling sessions before he figured it out (in
my experience any way).

I've not seen this sort of thing for a long time now. Twenty
years ago, with early C compilers, you could pretty much count
on the compiler being naïve, and that such code would gain you
a machine instruction or two. In the case of the original
Duff's device, for example, Duff clearly said that he only
implemented it because the other solutions had performance
problems.

On the other hand, you'll have to admit that such oddities can
be amusing. (I like the IOCCC, too.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,184
Messages
2,570,976
Members
47,536
Latest member
MistyLough

Latest Threads

Top