Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Why the usage of while(0)

Reply
Thread Tools

Why the usage of while(0)

 
 
Riccardo Manfrin
Guest
Posts: n/a
 
      12-04-2009
Hi list!
Having this code:
do {
if (flag_prg)
printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER);
} while (0)

why the use of while?
R
 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      12-04-2009
Riccardo Manfrin <(E-Mail Removed)> writes:

[This shoudl be a FAQ but I can't currently check since the C FAQ site
appears to be down.]

> Having this code:
> do {
> if (flag_prg)
> printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER);
> } while (0)
>
> why the use of while?


As you present it, none. In fact it's a syntax error since there is
no ; after the while (0). This is a big clue that the code comes
from a macro.

The purpose of the loop is syntactic. It encloses the 'if' in a
statement (when the ; is added by the macro invocation) so that no
surprises happen to the users of the macro. Consider the simpler:

#define PRINT_BANNER if (flag_prg) \
printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER)

and a usage like this:

if (first_run)
PRINT_BANNER;
else puts("Going again...";

The 'else' will be taken to be part of the inner if regardless of the
indentation. do {} while (0) gets round this and other potentials
problems with macros that expand to statements.

--
Ben.
 
Reply With Quote
 
 
 
 
Riccardo Manfrin
Guest
Posts: n/a
 
      12-04-2009
Thanks both Ben & pete!
mymistake not stating that was code within a #define statement.
Thanks for the explaination. Now I know the reason why.
R
 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      12-04-2009
On 2009-12-04, Riccardo Manfrin <(E-Mail Removed)> wrote:
> Hi list!
> Having this code:
> do {
> if (flag_prg)
> printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER);

^
Typo? Strange to have a lower case letter on the end of an all-caps
macro. I take it this is a plural, implying that expands into a
string literal containing two numbers separated by a period,
specifying the width an pecision for %s?

> } while (0)
>
> why the use of while?


That allows the whole thing to be a syntactically encapsulated statement
which requires a terminating semicolon, which is useful if it is
the expansion of a macro.

Suppose that you drop the do/while(0) and your macro just
expands this (note dropped semicolon).

if (flag_prg)
printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER)

Unlike do/while(0) this has problems. For instance, you can now
do something like this:

MACRO() + 3;

The + 3 happily goes onto the printf, so that it's obvious that MACRO()
is not a proper statement. But is it an expression? If so, this
should work:

var = MACRO();

but, nope, that breaks! You're assigning the value of an if statement,
oops!

Moreover, here is the kicker:

MACRO()
else { ... }

Look ma, you can continue the if statement that is started within the
macro expansion, by adding an else, and there is no compiler diagostic.

So you see this do/while(0) wrapping protects against crap like this.

Another good question is, why the cryptic compile-time string literal
manipulation instead of something straightforward, like:

prinf("%-*.*s", PROGNAME_WIDTH, PROGNAME_LIMIT, PROGNAME_BANNER);

A conversion like

"%-42.40s", string

isn't necessarily faster than

"%*.*s", width, prec, string

the reason is that if the format string is being interpreted, then the
42 and 40 have to be scanned and turned into values. Whereas the *
character allows printf to simply retrieve a ready-made integer value
from the arguments; no text-to-int conversion necessary.

You might have a performance win here if your your implementation has a
printf compiler which turns format strings into code.

Also, what is the purpose of this juxtaposition:

" " PROGNAME_BANNER

The extra space can easily be added under the control of the printf
format string. It's silly to be adding padding to the data.

Rather than "%s", " " MY_STRING you can just " %s", MY_STRING.
 
Reply With Quote
 
James Dow Allen
Guest
Posts: n/a
 
      12-05-2009
On Dec 4, 7:52*pm, Riccardo Manfrin <(E-Mail Removed)>
wrote:
> * * * * do {
> ....
> * * * * } while (0)


I once scanned through glibc source looking for instances of
this construction. I may as well report my results.

In
glibc-2.7/soft-fp/testit.c
there is, *inside* a switch block,
do {
case 'a': r = r_addsf3; t = ...; break;
case 's': r = r_subsf3; t = ...; break;
case 'm': r = r_mulsf3; t = ...; break;
case 'd': r = r_divsf3; t = ...; break;
case 'r': r = r_sqrtsf3; t = ...; break;
case 'j': r = r_negsf3; t = ...; break;
} while (0);
Although in a switch the "break"s here just break out of the
do while (0). In other words, the peculiar "do break while"
simply avoids what some of us would accomplish with
"goto commoncode;" I'd be interested to hear whether
anti-goto fanatics are fans of the above construction!

Another place where do while(0) was introduced, seemingly
just to avoid goto is in
nptl/pthread_mutex_setprioceiling.c
"break" and "continue" have, I think, *identical* meaning
inside the while(0); yet the code just mentioned uses
each of them! (Perhaps this is a vestigial remnant of
earlier version where the while predicate was other
than just 0.)

BTW, I also found *many* instances of the usual
do {...} while(0) macros, as well as two instances
argp/argp-help.c
elf/readelflib.c
with "while (0);" terminating the macro! I assume the
extra ";" were typos, not causing trouble since the
macros weren't used inside if or other troublesome cases.

James Dow Allen
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      12-05-2009
James Dow Allen wrote:
> On Dec 4, 7:52 pm, Riccardo Manfrin <(E-Mail Removed)>
> wrote:
>> do {
>> ....
>> } while (0)

>
> I once scanned through glibc source looking for instances of
> this construction. I may as well report my results.
>
> In
> glibc-2.7/soft-fp/testit.c
> there is, *inside* a switch block,
> do {
> case 'a': r = r_addsf3; t = ...; break;
> case 's': r = r_subsf3; t = ...; break;
> case 'm': r = r_mulsf3; t = ...; break;
> case 'd': r = r_divsf3; t = ...; break;
> case 'r': r = r_sqrtsf3; t = ...; break;
> case 'j': r = r_negsf3; t = ...; break;
> } while (0);
> Although in a switch the "break"s here just break out of the
> do while (0). In other words, the peculiar "do break while"
> simply avoids what some of us would accomplish with
> "goto commoncode;" I'd be interested to hear whether
> anti-goto fanatics are fans of the above construction!


If each `break' were changed to `continue', the code
would do the same thing but might be less susceptible to
mis-reading.

One wonders, though, why the "more natural" arrangement

switch (whatever) {
case 'a': r = ...; break;
case 's': r = ...; break;
...
}
... common code ...

wasn't used. Maybe the "common" code applies only to some
of the `switch' cases, and not to all? (That is, does the
`switch' have additional `case's outside the `do'?)

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
Antoninus Twink
Guest
Posts: n/a
 
      12-05-2009
On 5 Dec 2009 at 13:40, Eric Sosman wrote:
> Maybe the "common" code applies only to some of the `switch' cases,
> and not to all? (That is, does the `switch' have additional `case's
> outside the `do'?)


Presumably that's the whole point.

 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      12-05-2009
On 2009-12-05, Antoninus Twink <(E-Mail Removed)> wrote:
> On 5 Dec 2009 at 13:40, Eric Sosman wrote:
>> Maybe the "common" code applies only to some of the `switch' cases,
>> and not to all? (That is, does the `switch' have additional `case's
>> outside the `do'?)

>
> Presumably that's the whole point.


Yeah, well Sosman wouldn't just assume that people maintaining glibc
might have a point, right?

I am sure Drepper would never accept a patch containing weird code like
that unless there was a very good reason why it's done that way.
Avoding a ton of forward gotos is apparently such a reason.

That code is a big switch, with a number of repetitions of
the do/while(0) idiom.

It's the perfect iditom in the situation in which the switch cases group
into subsets, to which common code applies, but which also have to do
something unique for each member case.
 
Reply With Quote
 
James Dow Allen
Guest
Posts: n/a
 
      12-05-2009
On Dec 5, 8:40*pm, Eric Sosman <(E-Mail Removed)> wrote:
> James Dow Allen wrote:
> > In
> > * *glibc-2.7/soft-fp/testit.c
> > there is, *inside* a switch block,
> > * * * * * do {
> > * * * * * * *case 'a': r = r_addsf3; t = ...; break;
> > * * * * * * *case 's': r = r_subsf3; t = ...; break;

> . [snip]
> > * * * * * } while (0);
> > Although in a switch the "break"s here just break out of the
> > do while (0). *In other words, the peculiar "do break while"
> > simply avoids what some of us would accomplish with
> > "goto commoncode;" *I'd be interested to hear whether
> > anti-goto fanatics are fans of the above construction!

>
> One wonders, though, why the "more natural" arrangement
> ...
> wasn't used. *Maybe the "common" code applies only to some
> of the `switch' cases, and not to all?


Yes, sorry I didn't make this clear.

Actually there were three or so of these do while (0)'s
all within the same giant switch block. Moreover, there
were other blocks nesting between the switch and the do while's:
blocks just to declare local automatic variables.

This was all inside main() in a function named testit.c
so I suppose stylistic perfectionism is relaxed. Still
I would like to hear an answer to my question:
What do anti-goto fanatics think of this method of
avoiding goto?

James Dow Allen
 
Reply With Quote
 
Antoninus Twink
Guest
Posts: n/a
 
      12-05-2009
On 5 Dec 2009 at 18:59, James Dow Allen wrote:
> I would like to hear an answer to my question: What do anti-goto
> fanatics think of this method of avoiding goto?


Are there many anti-goto fanatics left? I thought most people nowadays
had grown up and taken a less dogmatic and more pragmatic approach to
programming.

(Heathfield is an obvious example of course - no position is too
ridiculous for him. I believe he also objects to having more than one
return statement in a function.)

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
retrieving CPU Usage and Memory Usage information in JAVA hvt Java 0 03-13-2007 01:07 PM
why why why why why Mr. SweatyFinger ASP .Net 4 12-21-2006 01:15 PM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
Webchecker Usage - a problem with local usage Colin J. Williams Python 1 02-26-2004 12:28 AM
Need help on memory usage VS PF usage metfan Java 2 10-21-2003 01:58 PM



Advertisments