Why the usage of while(0)

Discussion in 'C Programming' started by Riccardo Manfrin, Dec 4, 2009.

  1. Hi list!
    Having this code:
    do {
    if (flag_prg)
    printf("%-" PROGNAME_WIDTHs "s"," " PROGNAME_BANNER);
    } while (0)

    why the use of while?
    R
    Riccardo Manfrin, Dec 4, 2009
    #1
    1. Advertising

  2. Riccardo Manfrin <> 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.
    Ben Bacarisse, Dec 4, 2009
    #2
    1. Advertising

  3. 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
    Riccardo Manfrin, Dec 4, 2009
    #3
  4. Riccardo Manfrin

    Kaz Kylheku Guest

    On 2009-12-04, Riccardo Manfrin <> 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.
    Kaz Kylheku, Dec 4, 2009
    #4
  5. On Dec 4, 7:52 pm, Riccardo Manfrin <>
    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
    James Dow Allen, Dec 5, 2009
    #5
  6. Riccardo Manfrin

    Eric Sosman Guest

    James Dow Allen wrote:
    > On Dec 4, 7:52 pm, Riccardo Manfrin <>
    > 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
    lid
    Eric Sosman, Dec 5, 2009
    #6
  7. 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.
    Antoninus Twink, Dec 5, 2009
    #7
  8. Riccardo Manfrin

    Kaz Kylheku Guest

    On 2009-12-05, Antoninus Twink <> 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.
    Kaz Kylheku, Dec 5, 2009
    #8
  9. On Dec 5, 8:40 pm, Eric Sosman <> 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
    James Dow Allen, Dec 5, 2009
    #9
  10. 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.)
    Antoninus Twink, Dec 5, 2009
    #10
  11. Riccardo Manfrin

    Eric Sosman Guest

    Kaz Kylheku wrote:
    > On 2009-12-05, Antoninus Twink <> 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 asked "X?" I did not assert or imply either "X" or "!X",
    and anyone who assumes I did so is making an unfounded assumption.

    --
    Eric Sosman
    lid
    Eric Sosman, Dec 5, 2009
    #11
  12. Riccardo Manfrin

    Eric Sosman Guest

    James Dow Allen wrote:
    > [...] Still
    > I would like to hear an answer to my question:
    > What do anti-goto fanatics think of this method of
    > avoiding goto?


    Since anyone who answers implicitly asserts that he
    is in fact a "fanatic," there may be some reluctance to
    respond ...

    --
    Eric Sosman
    lid
    Eric Sosman, Dec 5, 2009
    #12
  13. On Dec 6, 2:25 am, Eric Sosman <> wrote:
    > 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?

    > .
    > Since anyone who answers implicitly asserts that he
    > is in fact a "fanatic," there may be some reluctance to
    > respond ...


    Sorry again; this superfluous pejorative was
    uncalled-for. But surely comments from any
    c.l.c'ers are welcome; admission or denial of
    fanaticism is optional. :)

    (Given that some c.l.c'ers proudly embrace the
    term "Pedant", I'd not be surprised if some happily
    acknowledge fanaticism. Probably I could be accused
    of fanaticism on some topics; e.g. refusal to
    issue blanket condemnation of 'goto'. :)

    But anyway, this particular usage of
    do {
    ... break;
    ... continue;
    } while (0);
    to avoid 'goto commoncase;' is uninteresting compared
    to the goto in
    http://james.fabpedigree.com/gotoalt.htm

    I *do* hope c.l.c'ers will read that page and comment.
    So far only two votes have been recorded:
    Tim votes for Tim's code.
    James votes for James' code.
    Others? (I'm tempted to confess, in another thread,
    that I use 'goto' in transition-machine code, but
    may not dare unless I get some votes in *this* poll.)

    James Dow Allen
    James Dow Allen, Dec 6, 2009
    #13
  14. Riccardo Manfrin

    Flash Gordon Guest

    James Dow Allen wrote:
    > On Dec 6, 2:25 am, Eric Sosman <> wrote:
    >> 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?

    >> .
    >> Since anyone who answers implicitly asserts that he
    >> is in fact a "fanatic," there may be some reluctance to
    >> respond ...

    >
    > Sorry again; this superfluous pejorative was
    > uncalled-for. But surely comments from any
    > c.l.c'ers are welcome; admission or denial of
    > fanaticism is optional. :)


    I'm not fanatical, but I have seen code which is horrendous in part due
    to the use of goto.

    > (Given that some c.l.c'ers proudly embrace the
    > term "Pedant", I'd not be surprised if some happily
    > acknowledge fanaticism. Probably I could be accused
    > of fanaticism on some topics; e.g. refusal to
    > issue blanket condemnation of 'goto'. :)
    >
    > But anyway, this particular usage of
    > do {
    > ... break;
    > ... continue;
    > } while (0);


    I've used that kind of pattern. I've also used a pattern of..

    static int dirtyfoo(params)
    {
    ret = ok
    do stuff
    if error return notsolateerror

    do stuff
    if error return verylateerror

    do stuff

    return OK
    }

    int foo(params)
    {
    ret = dirtyfoo(params)
    switch (ret) {
    case verylateerror: clean up late stuff
    case notsolateerror: clean up not so late stuff
    ...
    }
    return ret;
    }

    The cleanup stuff here was sending appropriate cleanup bits to an
    external system over a socket. The goto type alternative would have been

    int foo(params)
    {
    do stuff
    if error { ret = notsolateerror; goto notsolateerror }
    do stuff
    if error { ret = verylateerror; goto verylateerror }
    do stuff
    return OK

    verylateerror:
    clean up late stuff
    notsolateerror:
    clean up not so late stuff
    return ret
    }

    There were actually a hole load of sub functions, with sub functions,
    all returning statuses, with the status codes selected to I could just
    propagate them out to the external caller.

    I think my splitting out the work in to a sub-functions and abusing a
    switch for the cleanup worked well, especially as there was no cleanup
    if it was all OK.

    > to avoid 'goto commoncase;' is uninteresting compared
    > to the goto in
    > http://james.fabpedigree.com/gotoalt.htm
    >
    > I *do* hope c.l.c'ers will read that page and comment.
    > So far only two votes have been recorded:
    > Tim votes for Tim's code.
    > James votes for James' code.
    > Others?


    I would have to think hard about it, but it feels like some kind of
    recursive solution might be cleaner. Possibly a function for each of the
    loops in the first block, with the loop done by a recurse in each case,
    the retract done on the unwind with, of course, a done result allowing
    you to unwind without retracting. I'm not up to working it out at the
    moment, in part due to not understanding the problem being solved by it.

    > (I'm tempted to confess, in another thread,
    > that I use 'goto' in transition-machine code, but
    > may not dare unless I get some votes in *this* poll.)


    Well, I've used loops, switches and state variable for state machines
    where others use gotos in the past. I seem to remember also using a
    function table and state variable once for a state machine...
    initialise state
    loop
    state = call action[state]
    until state is finished
    so each function in the action array returned the next state, all nicely
    named with an enum.

    I will use goto sometimes, mainly for exception handling.
    --
    Flash Gordon
    Flash Gordon, Dec 6, 2009
    #14
  15. Riccardo Manfrin

    Nick Guest

    James Dow Allen <> writes:

    > 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.


    I do the latter, although I'm never very happy about it:
    switch(a) {
    case 10:
    {
    int p,r,s;
    ... do stuff with p,r and s ...
    break;
    }
    case 11:
    }

    In a really fiddling point of style, I often wonder which side of close
    brace the "break" should be.
    --
    Online waterways route planner: http://canalplan.org.uk
    development version: http://canalplan.eu
    Nick, Dec 6, 2009
    #15
  16. Riccardo Manfrin

    Guest

    On Fri, 04 Dec 2009 13:14:00 +0000 Ben Bacarisse <> wrote:
    | Riccardo Manfrin <> 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.

    Do you have an example where enclosing in plain { } is not good enough?

    --
    -----------------------------------------------------------------------------
    | Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
    | (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
    -----------------------------------------------------------------------------
    , Dec 6, 2009
    #16
  17. Riccardo Manfrin

    Guest

    On Sat, 5 Dec 2009 19:07:02 +0000 (UTC) Antoninus Twink <> wrote:

    | 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.

    What is the difference between an anti-goto fanatic and an anti-goto
    advocate?

    What about the anti-goto-into-the-middle-of-a-loop fanatics?

    --
    -----------------------------------------------------------------------------
    | Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
    | (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
    -----------------------------------------------------------------------------
    , Dec 6, 2009
    #17
  18. On Dec 6, 4:33 pm, Flash Gordon <> wrote:
    > James Dow Allen wrote:
    > >    http://james.fabpedigree.com/gotoalt.htm

    > .
    > > I *do* hope c.l.c'ers will read that page and comment.
    > > So far only two votes have been recorded:
    > >    Tim votes for Tim's code.
    > >    James votes for James' code.
    > > Others?

    > .
    > I would have to think hard about it, but it feels like some kind of
    > recursive solution might be cleaner....


    You could be right (though perhaps a somewhat different
    recursion than you outline), and end up with code more
    readable than either James' or Tim's, though somewhat slower.
    I'm not sure how much slowdown would be acceptable while
    still conceding superiority.

    But only Tim and James have taken the time to actually
    produce working code. *If you're forced to choose
    between these two versions*, which would you pick?

    James
    James Dow Allen, Dec 6, 2009
    #18
  19. Riccardo Manfrin

    Phil Carmody Guest

    Nick <> writes:
    > switch(a) {
    > case 10:
    > {
    > int p,r,s;
    > ... do stuff with p,r and s ...
    > break;
    > }
    > case 11:
    > }
    >
    > In a really fiddling point of style, I often wonder which side of close
    > brace the "break" should be.


    case pairs with break, as the case is outside the {, the break
    should be outside the }. I find that observance of that to be
    very rare compared to the style you quote.

    Phil
    --
    Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
    Phil Carmody, Dec 6, 2009
    #19
  20. writes:

    > On Fri, 04 Dec 2009 13:14:00 +0000 Ben Bacarisse <> wrote:
    > | Riccardo Manfrin <> writes:

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

    <snip>
    > | 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...";


    I missed a ) but that is not significant.

    > | 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.
    >
    > Do you have an example where enclosing in plain { } is not good
    > enough?


    The example I gave is already one -- the usage becomes complex.
    PRINT_BANNER is now different (syntactically) to PRINT_BANNER;

    --
    Ben.
    Ben Bacarisse, Dec 6, 2009
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. metfan
    Replies:
    2
    Views:
    4,832
    Robert Olofsson
    Oct 21, 2003
  2. Colin J. Williams

    Webchecker Usage - a problem with local usage

    Colin J. Williams, Feb 25, 2004, in forum: Python
    Replies:
    1
    Views:
    520
    Colin J. Williams
    Feb 26, 2004
  3. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    853
    Mark Rae
    Dec 21, 2006
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,739
    Smokey Grindel
    Dec 2, 2006
  5. hvt
    Replies:
    0
    Views:
    1,190
Loading...

Share This Page