3

What is the significance of do while loop when the condition inside the while loop is 0 i.e. always false.

do
{

//some code implementation.

}while(0);

I have seen at many places this is being used. What is its importance, Cant we just omit the do while(0). as both ways code will be executed only once.

It is not a duplicate as i asked about use of while(0) condition specifically not general do-while loop.

Aragon
  • 1,551
  • 1
  • 15
  • 25
  • 3
    If it's not a macro, then it's probably in order for the author to be able to use `break;` to jump to the end of the block. Some people want to avoid `goto` whatever the cost. – Daniel Fischer May 06 '13 at 11:40
  • a simple Google search would have brought you the answer – phaazon May 06 '13 at 11:48
  • 2
    @levengli: No, it is not a duplicate. Daniel: Some languages like java have no "goto" keyword, so jumping forward to a specific point needs to be done with either a labeled break or a do/while. The last one is preferable because the labeled break syntax may be confusing. – Thorsten S. May 06 '13 at 11:49
  • 1
    Agree with Thorsten its not a duplicate. So the main reason to use this is to perform a jump if needed without using goto etc. – Aragon May 06 '13 at 11:51
  • The `do { /* block */ } while (0);` executes a block of code once, **terminating with a semicolon** (compare with `{ /* block */ }`). That's required for some macros. – pmg May 06 '13 at 11:59
  • @ThorstenS. Java has (or had, I didn't check, so it might have been removed) a `goto` keyword. It's just not used/usable. But yes, if it was Java, `goto` wouldn't be an alternative. However, the question is tagged C, so I only considered that for the comment. – Daniel Fischer May 06 '13 at 12:00
  • @DanielFischer: One disadvantage of the goto solution is that the scope of the jumping points is not immediately obvious. So if I find a multiple goto forward jump in some other code, I indent the code block from the first to the last jump and set the label apart with one return before and after to be easily visible. – Thorsten S. May 06 '13 at 12:12
  • Think of it as a C variant of `try { ... } catch()` with `break` acting as `throw()`. – SF. Oct 07 '14 at 10:59

3 Answers3

2

It can be used to leave a certain scope of code at any point without leaving the function. Consider:

do
{
  beginAtomicOperationSequence();

  ret = doSomething();
  if (ret < 0) break;

  ret = doSomething2();
  if (ret < 0) break;

} while(0);

if (ret < 0) {
  switch (ret) {
   //handle error
  }
  rollbackAboveOperations();
} else {
  commitAboveOperations();
}

There are some cases in which I would say that this is acceptable, particularly if one needs to make a sequence of operations which are to be considered atomic. Like in the example above.

Dariusz
  • 21,561
  • 9
  • 74
  • 114
  • 1
    Referring "*... not good practice ...*": Cascading `if(...) if (...) if (...) ...` are worth, and `goto`s even worther! – alk May 06 '13 at 11:44
  • @alk worth? worse? Anyway, as I said, there are only some cases this is acceptable. True, cascading ifs is much worse in terms of code readability. – Dariusz May 06 '13 at 11:48
  • @Dariusz: What is the alternative if it is not a good practice ? – Thorsten S. May 06 '13 at 11:50
  • @ThorstenS. designing your code in a way that would not require such constructs. More thoughtful splitting code into functions. Handling each return code separately. But yeah, I'll change the good practice bit of my answer, because it is misleading and not what I meant. – Dariusz May 06 '13 at 11:52
  • 1
    @Dariusz: This is for many languages like C not an option because return codes must be handled and even if you have a capability, I am not sure you should try to avoid it. The typical handling of this construct is to do something which needs many independent steps and any failed step will cause a fail. The do/while solution is fine because it is easy to understand and boring, a perfect candidate for KISS. – Thorsten S. May 06 '13 at 12:03
  • @ThorstenS. I see your point and I agree. As I said, I do it sometimes, exactly in such cases. I'm not sure if KISS applies here, since this construct apparently causes some confusion for those unfamiliar with it. – Dariusz May 06 '13 at 12:07
  • @Dariusz: Worse! Sry ... S-} – alk May 06 '13 at 12:13
  • 1
    `break` is just `goto` without the label but since it's spelled differently it allows people to pay lip service to a catchy title added by an editor to an outdated article talking about an esoteric topic not relevant to modern software engineering. – Art May 06 '13 at 12:34
  • @Art I don't use goto for one reason: I don't like the syntax. All of a sudden I have a random label somewhere in my code, I don't really know how to intend it, and for me it destroys code readability. When I see a break, I proceed to the ending brace. For goto - I have to look for it, and it can be anywhere. The efficiency of both is probably exactly the same. Also, goto has the possibility of messing the code up a lot. If you place it in the wrong place... – Dariusz May 06 '13 at 12:39
  • I would agree that this code is worse than a down-jumping goto. The best practice is most likely to put all the if statements in a separate function and return from it upon error. That's easiest to read and you can include an error code. That being said, `do while(0)` is most often (only?) used in one case, and that is to save a program already cluttered with other kinds of bad practice from bugs. Namely a program with function-like macros (BAD) in combination with statements that have no following {} (most of the time, bad). – Lundin May 06 '13 at 12:55
  • ...on the other hand, go to is considered harmful... :) – Lundin May 06 '13 at 12:56
  • @Dariusz If your label is so far away that you can't find it immediately, then it will be even worse to find a `}` (which will be one among many). This will also mean that the code is already badly structured and hiding the obvious will not help. – Patrick Schlüter May 06 '13 at 13:00
  • @Lundin you are 100% right about the function-encapsulation of the whole process, but the problem is that in real-world applications there are a lot of local variables in that function which contain information useful for logs/debug. So then we have to add a (virtually the same) separate error message each time we call return from that function. – Dariusz May 06 '13 at 13:00
  • @Tristopia I can find the `}` with a single keyboard shortcut. http://wiki.codeblocks.org/index.php?title=Matching_Brace – Dariusz May 06 '13 at 13:02
  • @Dariusz Why is keeping the actual algorithm apart from logging/error handling bad? Seems like excellent program design to me. `result = the_sub_function(some_locals); if (result != OK) log(result, some_locals);`. – Lundin May 06 '13 at 13:06
  • @Lundin It's the other way round. It's not about parameters, but the locals. Variables are declared in the "long process" sub-function. – Dariusz May 06 '13 at 13:09
  • And I can find the goto label with a mouse click and pressing F3, so what? It is still easier to **read** a well placed, meaningful label than one brace among many braces. And to be clear, I'm not advocating the indiscriminate use of `goto`, I'm just ranting about using a construct that is essentially the same thing in worse, adding a layer of obfuscation on it by hijacking another concept (the loop). – Patrick Schlüter May 06 '13 at 13:14
  • @tristopia it was your argument that it's hard to find, I know it isn't (both aren't). But in all this discussion you're missing the point of the question, which was "why use while(0)". In this case goto may be better and more readable for some people, maybe even for most, but **that was not the question!** – Dariusz May 06 '13 at 13:18
2

It ensures the macro always behaves the same, regardless of how semicolons and curly-brackets are used in the invoking code.

For more details refer to this

GeekFactory
  • 399
  • 2
  • 13
1

The do { } while(0) construct in that context, is an obfuscated way to write goto's without actually writing it out. It is used by cargo cult programmers who somewhere read that gotos are bad but didn't understand why.

Here the example of Dariusz' answer rewritten with a proper goto and a meaningfull label.

  beginAtomicOperationSequence();

  ret = doSomething();
  if (ret < 0) goto handle_error;

  ret = doSomething2();
  if (ret < 0) goto handle_error;

  ...

handle_error:
  if (ret < 0) {
    switch (ret) {
    //handle error
    }
    rollbackAboveOperations();
  } else {
    commitAboveOperations();
  }

As can be seen it is shorter and completely obvious. That you even had to ask for the purpose of that construct shows that it is a bad idea.

I am vehement in my answer, because I have a colleague who uses and abuses it in our project and I haven't found one redeeming value to it. It gets even more annoying when you add some real loops in the mix. Then the fun starts to find where the break and continue will lead you to.

Patrick Schlüter
  • 11,394
  • 1
  • 43
  • 48
  • I think this code is bad. Not because of goto. `handle_error` should handle an error, not perform a commit if all is ok. The proper way to do it would be to put the `handle_error` after the *all went OK* normal return statement. – Dariusz May 06 '13 at 12:22
  • BTW: this answer has nothing to do with the question. You should delete it. – Dariusz May 06 '13 at 12:23
  • And if I may add my 2 cents, I *hate* one-line ifs because even with syntax highlighting they are easy to oversee and your debugger step behavior is undefined. – Thorsten S. May 06 '13 at 12:37
  • Reworded it to make a proper answer and I won't delete it. It is my opinion that this construct should never be used. Ever. It has not upside whatsoever. – Patrick Schlüter May 06 '13 at 12:53
  • More likely, do while(0) is used to save function-like macros from going haywire when invoked from `if(x) FUNCTION_LIKE_MACRO();` – Lundin May 06 '13 at 13:00
  • My rant is only about the construct used to replace `goto`'s by `break`. The `do { }while(0)` in function like macros is absolutely necessary. It isn't a problem for lisibility either, because it only exists in the place of definition of the macro, not where it is used. – Patrick Schlüter May 06 '13 at 13:04
  • Personally, I don't write gotos, I don't write function-like macros and I always use `{}`. Thus I never write do-while(0) either. But then I never quite liked obscure program constructs as solutions to meta-programming-problems created by the programmer themselves. Weird huh? – Lundin May 06 '13 at 13:13