154

I was looking at some code by an individual and noticed he seems to have a pattern in his functions:

<return-type> function(<params>)
{
 <initialization>

 do
 {
   <main code for function>
 }
 while(false);

 <tidy-up & return>
}

It's not bad, more peculiar (the actual code is fairly neat and unsurprising). It's not something I've seen before and I wondered if anyone can think of any logic behind it - background in a different language perhaps?

Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157
Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • 3
    Have you tried changing it to the "normal" version and seeing if it still compiles? If it fails to compile when written normally, the compiler error could give a clue as to why this was done. – Mark Byers Feb 22 '10 at 20:55
  • 13
    Why not ask the "individual" rather than asking us for guesses on his intention? –  Feb 22 '10 at 20:57
  • 1
    Maybe his professor required he use a `do...while()` and he has used that code as a function template since. – Hogan Feb 22 '10 at 21:01
  • @Neil - Who knows how old that code is... the original author could be long gone, or no way to identify who wrote it. – Nick Feb 22 '10 at 21:02
  • @Nick Why do you feel the need to make further guesses? Why not let the questioner answer for himself? –  Feb 22 '10 at 21:09
  • 7
    @Neil... I want to avoid looking dumb when I confront him and he explains the super-advanced C++ usage I never thought of. – Mr. Boy Feb 22 '10 at 21:14
  • 1
    Since this makes the code in the braces execute exactly once, it seems very odd but also harmless. Can you give just a slightly fuller example of what goes on between the braces? – egrunin Feb 22 '10 at 21:16
  • 7
    There seems to be quite a few different answers already, can you ask the original author what their intentions were and post back? – nevets1219 Feb 22 '10 at 21:25
  • 3
    Guido van Rossum's CPython code uses this pattern extensively. It's mainly used inside of macro definitions, but occasionally in other code. I had wondered if there was another reason apart from the goto issue, since he doesn't shy away from using goto elsewhere in the code. The other explanations offered: forced post-macro semi-colon and lack of portability of free braces also sound convincing. Perhaps a CPython contributor will comment... – QuesterZen Aug 09 '16 at 03:09
  • 1
    Does this answer your question? [Why use apparently meaningless do-while and if-else statements in macros?](https://stackoverflow.com/questions/154136/why-use-apparently-meaningless-do-while-and-if-else-statements-in-macros) – A.R.C. Jan 28 '21 at 13:30

25 Answers25

214

You can break out of do{...}while(false).

Thomas Eding
  • 35,312
  • 13
  • 75
  • 106
  • 1
    Very good point there. Didn't think of that. Using gotos without using "goto" :D – Goz Feb 22 '10 at 20:54
  • 103
    +1 because that's probably the intent of the code, but doing something like this is just an idiotically disguised goto. If you think a goto is the right tool for the job, then you should just use a #$(*#@ goto. – dsimcha Feb 22 '10 at 20:55
  • 3
    Or `continue`. But I'd better use nested `if` instead. – Ivan Nevostruev Feb 22 '10 at 20:56
  • 71
    It's more than a disguised goto. It is a restricted (structured) goto. – Thomas Eding Feb 22 '10 at 20:56
  • 19
    In what way is it "restricted"? Only jumping forwards is hardly a "restriction". A goto is a goto, and dressing one up to make it look like it's not one is worse than just using a goto in the first place. – Anon. Feb 22 '10 at 20:58
  • 49
    @Anon.: Jumping forwards is a restriction on a goto, and jumping out is definitely a restriction. The real problem with gotos is spaghetti code, and a forward and out jump limits that greatly. – David Thornley Feb 22 '10 at 21:01
  • 3
    You will not make this code simplier by this trick. So it should be avoided. You can replace it with simple `if/else` logic. – Ivan Nevostruev Feb 22 '10 at 21:01
  • I've seen this done in C code, but in C++ it's rare. I see exceptions used in this manner for C++ more often. – Joel Feb 22 '10 at 21:01
  • 35
    An actual loop is not semantically a goto. A conditional is not semantically a goto. "Go to the end of the function and do the cleanup code" *is* semantically a goto. Use gotos when the semantics apply, don't dress up something semantically different because you're scared of them. – Anon. Feb 22 '10 at 21:02
  • 4
    An even better technique is to wrap your block of code into a function and return out of the function. As an aside, I definitely prefer goto over `if(x){do {/*stuff*/}while(false)}`. And don't ask me to use a giant if statement like that without giving it a block. Goto wins. – Brian Feb 22 '10 at 21:08
  • 11
    Personally I have seen this idiom enough times where I don't see it as awkward. The reason I would use this over goto would be so I wouldn't have to search for the label the goto would point to (which theoretically could be before the goto statement). Instead, all I would have to do would be to follow the indentation of the code. – Thomas Eding Feb 22 '10 at 21:20
  • 15
    Not only can you `break` out, you can `continue` out as well. Yuck. – Adrian McCarthy Feb 22 '10 at 21:22
  • 25
    I disagree with the goto advocates: merely having the token "goto" in a function immediately increases the cognitive load of reasoning about that function. It's not so much about what the code actually does, but what it might do, based on your imperfect understanding of it. Our time is limited; we can't understand all of everything instantly. Don't make me nervous by having a goto in there. If you find this idiom "weird" or unfamiliar, you need to read more code until it becomes familiar to you. – Bernd Jendrissek Apr 07 '10 at 17:30
  • 2
    You should be thankful that nobody thought of hiding the goto behind a macro which says BREAK or something. – Daniel Daranas Jun 20 '13 at 13:20
  • 2
    I think one must avoid using this idiom. You will not be able to use `break` to get out of `do{...}while(false)` inside an inner loop. Hmm.. a polymorphic `break`! – Benji Mizrahi Aug 18 '15 at 13:22
  • @BerndJendrissek What this pattern allows is to go somewhere forward in the code when one breaks out of the loop. It requires a tiny amount of thinking to determine where that is. Moreover, one doesn't recognize this pattern as such until one reads the very last line `while (true)`. A `goto` tells explicitly, and in the same line what is happening and where to go. – Anna Taurogenireva May 02 '17 at 15:18
  • C++ provides another way of writing “Go to the end of the function and do the cleanup code” without using the verboten word `goto`: `try`...`throw`...`catch`. – dan04 May 19 '17 at 03:31
  • 1
    So what we're really saying is that `do{break}while(false)` is the non-exceptional equivalent of `try{throw}finally{}`? – cwharris Oct 16 '17 at 19:10
  • 1
    No, it's kind of like a soft return. – Thomas Eding Oct 17 '17 at 14:20
  • 2
    Replacing it with if/else logic could sometimes result in overly nested ifs (imagine having 10 layers of brackets!). If it makes sense to use "do while false" then the only reasonable alternative to avoid ugly code is to make it a function and use return instead of break. Which makes clear the point that it's not a disguised goto at all, otherwise returning early from a function would also be a disguised goto. Also, I'm quite surprised at how many advocate using a goto instead--never use goto, EVER! – John Thoits Jan 04 '18 at 20:48
  • 1
    an immediately invoked lambda looks like a better solution to me nowadays. – nnolte Feb 06 '20 at 10:40
  • 2
    I used this extensively in the past. If you're doing a sequence of dependent operations (FindRsrc, LoadRsrc, LockRsrc, GetRsrcPtr), the levels of nesting start to become annoying, and error handling and cleanup can get really convoluted. With break, you can log the failure, then skip dependent code and clean up just below the loop. You know what you don't need to clean up, because the variables are NULL. – Scott Smith Nov 20 '20 at 14:30
  • Very old topic and a comment now may not be seen. I'm not a strong proponent of this idiom, but I do like it. I like the "sensibility" of how it reads through the code. "If something is 'wrong' _break from this path_!" I freely admit, it was strange when I first saw it, but it's familiar now. – Andrew Falanga Jun 20 '23 at 19:11
155

A lot of people point out that it's often used with break as an awkward way of writing "goto". That's probably true if it's written directly in the function.

In a macro, OTOH, do { something; } while (false) is a convenient way to FORCE a semicolon after the macro invocation, absolutely no other token is allowed to follow.

And another possibility is that there either once was a loop there or iteration is anticipated to be added in the future (e.g. in test-driven development, iteration wasn't needed to pass the tests, but logically it would make sense to loop there if the function needed to be somewhat more general than currently required)

frogatto
  • 28,539
  • 11
  • 83
  • 129
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 26
    +1 for mentioning the utility of this in macros; I'm surprised no one else mentioned that! – Nick Meyer Feb 22 '10 at 21:28
  • 7
    Yep, the macro thing is actually a perfectly valid usage of this. Of course, outside macros, it is just silly... ;) – jalf Feb 22 '10 at 21:40
  • 13
    It's not awkward, it's useful, because it's a *Scoped* goto - it means that any variables you declare in the do loop get destroyed, whereas the goto doesn't do that. – Ana Betts Feb 22 '10 at 23:06
  • 10
    @Paul: Nothing prevents you from adding braces around a bunch of statements to force this behavior with goto. – erikkallen Feb 23 '10 at 11:57
  • 5
    @Paul: goto out of a block most definitely causes local variables to be destroyed in C++, same as break. And in C variables aren't really destroyed, their stack space is simply reclaimed. – Ben Voigt Feb 23 '10 at 16:00
  • @Ben @Erik You can get the same effect using braces too, true. Though I always find braces around arbitrary blocks of code to be a "only if you have to" kind of construction. – Ana Betts Feb 23 '10 at 17:26
  • ++ for your second paragraph. I've seen and used that for a long time. – Mike Dunlavey Mar 11 '10 at 15:12
  • 2
    Agreed, but I don't understand how the 3rd paragraph is a benefit: either it's cruft that no longer makes sense and should be removed, or you should not have it in the first place---even if iteration is anticipated, you should add it *then*, before needed it's YAGNI. –  Mar 19 '10 at 02:13
  • @Roger: I was offering *possible* reasons for it, never suggested they were good valid reasons. – Ben Voigt Mar 19 '10 at 14:55
  • 1
    Cast an upvote for the capitalized FORCE in the answer. Before seeing this I was always wondering why not just `#define` something blank if you simply don't want it in a conditional branch in macro. Thanks for the explanation! – aafulei Oct 22 '18 at 08:08
27

The break as goto is probably the answer, but I will put forward one other idea.

Maybe he wanted to have a locally defined variables and used this construct to get a new scope.

Remember while recent C++ allows for {...} anywhere, this was not always the case.

Hogan
  • 69,564
  • 10
  • 76
  • 117
  • 33
    He could have just used curly braces in that case. – Nemanja Trifunovic Feb 22 '10 at 21:16
  • 2
    @Nemanja, you'd be surprised at how many developers don't know that and try something related to what Hogan is suggesting – DigitalZebra Feb 22 '10 at 21:24
  • 8
    @Polaris @Nemanja, it wasn't til I had been programming in C/C++ like 4 years that I figured out you can create a new local scope `{}` *anywhere*.. This is especially handy in `switch-case` code – Earlz Feb 22 '10 at 21:37
  • 1
    @Nemanja: I don't know exactly when, but I'm sure the `{...}` anywhere is a more modern development in C++ (remember the first C++ I used was implemented with a pre-processor and that did not allow this modern usage.) Maybe the author was just way old school. – Hogan Feb 22 '10 at 22:21
  • 2
    When did it not allow for braces everywhere? I started programming like 15 years ago, and it was allowed then (both in my text book and in every compiler I tried). – erikkallen Feb 23 '10 at 11:59
  • 1
    Prior to C89 the standard of statement blocks was not clear (it is not something described in K+R) so it was not portable. Some compilers supported it and some did not. Because of popularity (and use) it started to be supported almost across the board prior to the final draft of the standard, but was not official till then. (PS -- I don't have my copy of K+R handy so I could be wrong about this, but this is how I remember it, it was a while ago, please let me know if my memory is wrong.) – Hogan Feb 23 '10 at 13:46
  • 1
    "Recent" is misleading, at best. –  Mar 19 '10 at 02:15
  • 1
    @Roger : To true. -When I wrote it recent was relative to the time I worked with C, didn't think about how that was a "few" years ago. – Hogan Mar 19 '10 at 13:08
24

I've seen it used as a useful pattern when there are many potential exit points for the function, but the same cleanup code is always required regardless of how the function exits.

It can make a tiresome if/else-if tree a lot easier to read, by just having to break whenever an exit point is reached, with the rest of the logic inline afterwards.

This pattern is also useful in languages that don't have a goto statement. Perhaps that's where the original programmer learnt the pattern.

Cameron
  • 96,106
  • 25
  • 196
  • 225
  • 16
    Then just use an honest, straightforward goto instead of a thinly disguised goto. – dsimcha Feb 22 '10 at 20:56
  • 4
    I like this way better. It is easy to read and doesn't carry the stigma of a goto. – Cameron Feb 22 '10 at 20:57
  • 8
    gotos are perfectly easy to read if used sparingly and locally. They got their stigma from back when they were the main form of flow control and were jumping across hundreds of lines. – dsimcha Feb 22 '10 at 20:59
  • 13
    Not using goto because of a "stigma" is a sure sign of cargo-cult programming. – Anon. Feb 22 '10 at 20:59
  • 6
    Not to mention that a mass of cleanup code is a bad smell. This being C++, cleanup code should normally be in destructors called during RAII processing. – David Thornley Feb 22 '10 at 21:02
  • 1
    Maybe it is better to use RAII and let destructors execute any cleanup code (when the language is C++) – Yukiko Feb 22 '10 at 21:07
  • It can be used for other purposes besides cleanup code, for example when validating user input and multiple things could go wrong, there could be a variable valid = false, then a do ... while () loop with valid = true at the bottom, and after the loop would go an if checking if valid is true or not. – Cameron Feb 22 '10 at 21:10
  • 2
    There's some circular reasoning going on here. A long complicated function which would require such a construct is exactly the place `goto`'s are considered harmful. You tell yourself "oh it's just the one" and then a couple weeks later you have to put a special case in that bypasses the cleanup code. If you're having all this trouble with complex control flow, your first instinct should be to refactor the code and make it more modular. – wds Feb 23 '10 at 15:36
  • 1
    The "stigma" of `goto` is irrelevant. It's the equivalent to saying *people* shouldn't touch a jet engine just because *children* shouldn't touch a jet engine. A real reason you wouldn't touch a jet engine is if you're just trying to dry your hair. Sure, a jet engine works, but it comes with a lot more overhead than just picking it up off your counter and flipping a switch. `goto` is a jet engine. It provides a lot of power and flexibility at the price of cognitive overhead. If you *need* the flexibility, definitely use it. If you don't, then try not to add the extra overhead. – cwharris Oct 16 '17 at 19:16
  • @wds If you're having explicitly bypass cleanup by using a goto, *maaaaaaybe* you shouldn't be in that code in the first place. – cwharris Oct 16 '17 at 19:19
  • @ChristopherHarris My comment as I reread it now was wrong. It's been 7 years, so I'm not sure what I was even trying to say. As long as the cleanup code truly is common, this construct works great, since everything eventually has to go through there (or either early return or cleanup, e.g. usually the goto is to an error-case cleanup). – wds Oct 17 '17 at 02:21
  • This is **not** equivalent to a `goto`. With a goto, the scope of references to it is potentially much larger. This specifically says 'I need to exit this block at the bottom' (and nowhere else). Any variables defined below the break will be out-of-scope. It can also force stack-based variables/objects out of scope. – Scott Smith Nov 20 '20 at 14:39
12

I've seen code like that so you can use break as a goto of sorts.

Brian Young
  • 1,748
  • 13
  • 11
12

I think it's more convenient to write break instead of goto end. You don't even have to think up a name for the label which makes the intention clearer: You don't want to jump to a label with a specific name. You want to get out of here.

Also chances are you would need the braces anyway. So this is the do{...}while(false); version:

do {
   // code
   if (condition) break; // or continue
   // more code
} while(false);

And this is the way you would have to express it if you wanted to use goto:

{
   // code
   if (condition) goto end;
   // more code
}
end:

I think the meaning of the first version is much easier to grasp. Also it's easier to write, easier to extend, easier to translate to a language that doesn't support goto, etc.


The most frequently mentioned concern about the use of break is that it's a badly disguised goto. But actually break has more resemblance to return: Both instructions jump out of a block of code which is pretty much structured in comparison to goto. Nevertheless both instructions allow multiple exit points in a block of code which can be confusing sometimes. After all I would try to go for the most clear solution, whatever that is in the specific situation.

Robert
  • 2,603
  • 26
  • 25
  • Oh, I just noticed that I didn't understand the question completely before answering. I thought it was about the use of `do{ ... }while(false);` in general. But actually it's about using it to emulate some kind of `try{ ... }finally{ ... }`. – Robert Jun 19 '12 at 13:14
  • Nice observation of the parallel between break and return rather than goto. Agree that clearest solution is the best. In many cases it's probably clearer to encapsulate code like this in it's own separate function that uses return rather than break and then do the cleanup in the calling function. – persiflage Mar 28 '18 at 15:04
10

This is just a perversion of while to get the sematics of goto tidy-up without using the word goto.

It's bad form because when you use other loops inside the outer while the breaks become ambiguous to the reader. "Is this supposed to goto exit? or is this intended only to break out of the inner loop?"

John Knoeller
  • 33,512
  • 4
  • 61
  • 92
9

Several explanations. The first one is general, the second one is specific to C preprocessor macros with parameters:

Flow control

I've seen this used in plain C code. Basically, it's a safer version of goto, as you can break out of it and all memory gets cleaned up properly.

Why would something goto-like be good? Well, if you have code where pretty much every line can return an error, but you need to react to all of them the same way (e.g. by handing the error to your caller after cleaning up), it's usually more readable to avoid an if( error ) { /* cleanup and error string generation and return here */ } as it avoids duplication of clean-up code.

However, in C++ you have exceptions + RAII for exactly this purpose, so I would consider it bad coding style.

Semicolon checking

If you forget the semicolon after a function-like macro invocation, arguments might contract in an undesired way and compile into valid syntax. Imagine the macro

#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");

That is accidentally called as

if( foo )
    PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
    doSomethingElse();

The "else" will be considered to be associated with the gDebugModeOn, so when foo is false, the exact reverse of what was intended will happen.

Providing a scope for temporary variables.

Since the do/while has curly braces, temporary variables have a clearly defined scope they can't escape.

Avoiding "possibly unwanted semicolon" warnings

Some macros are only activated in debug builds. You define them like:

#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n) 
#endif

Now if you use this in a release build inside a conditional, it compiles to

if( foo )
    ;

Many compilers see this as the same as

if( foo );

Which is often written accidentally. So you get a warning. The do{}while(false) hides this from the compiler, and is accepted by it as an indication that you really want to do nothing here.

Avoiding capturing of lines by conditionals

Macro from previous example:

if( foo )
    DBG_PRINT_NUM(42)
doSomething();

Now, in a debug build, since we also habitually included the semicolon, this compiles just fine. However, in the release build this suddenly turns into:

if( foo )

doSomething();

Or more clearly formatted

if( foo )
    doSomething();

Which is not at all what was intended. Adding a do{ ... }while(false) around the macro turns the missing semicolon into a compile error.

What's that mean for the OP?

In general, you want to use exceptions in C++ for error handling, and templates instead of macros. However, in the very rare case where you still need macros (e.g. when generating class names using token pasting) or are restricted to plain C, this is a useful pattern.

uliwitness
  • 8,532
  • 36
  • 58
  • Regarding scoping, you don't need the loop apparatus; an "unadorned" block is legal: `x =1; y = 2; { int tmp = y; y = x; x = tmp; }`. – chepner Aug 24 '17 at 12:16
  • An unadorned block doesn't enforce the presence of a missing semicolon though, which could have undesired side effects. Do{} while(); REQUIRES the semicolon and thus e.g. Doesn't cause following statements to be drawn into an "if" if the macro defines to nothing in a release build, like my example above. – uliwitness Sep 06 '17 at 16:15
  • Couldn't that be avoided by simply providing a better definition for the macro? `#define DBG_PRINT_NUM(n) {}`. – chepner Sep 06 '17 at 16:25
  • 1
    No, because {} is a full statement, i.e. equivalent to a ";". So if you write `if(a) DBG_PRINT_NUM(n); else other();` It will not compile. Only `if(a) {} else other();` or `if(a) ; else other();` is valid, but `if(a) {}; else other();` isn't, because that makes the "if" clause consist of two statements. – uliwitness Sep 08 '17 at 13:23
8

This trick is used by programmers that are too shy to use an explicit goto in their code. The author of the above code wanted to have the ability to jump directly to the "cleanup and return" point from the middle of the code. But they didn't want to use a label and explicit goto. Instead, they can use a break inside the body of the above "fake" cycle to achieve the same effect.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
7

It looks like a C programmer. In C++, automatic variables have destructors which you use to clean up, so there should not be anything needed tidying up before the return. In C, you didn't have this RAII idiom, so if you have common clean up code, you either goto it, or use a once-through loop as above.

Its main disadvantage compared with the C++ idiom is that it will not tidy up if an exception is thrown in the body. C didn't have exceptions, so this wasn't a problem, but it does make it a bad habit in C++.

Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171
7

It is a very common practice. In C. I try to think of it as if you want to lie to yourself in a way "I'm not using a goto". Thinking about it, there would be nothing wrong with a goto used similarly. In fact it would also reduce indentation level.

That said, though, I noticed, very often this do..while loops tend to grow. And then they get ifs and elses inside, rendering the code actually not very readable, let alone testable.

Those do..while are normally intended to do a clean-up. By all means possible I would prefer to use RAII and return early from a short function. On the other hand, C doesn't provide you as much conveniences as C++ does, making a do..while one of the best approaches to do a cleanup.

Dmitry
  • 6,590
  • 2
  • 26
  • 19
2

Maybe it’s used so that break can be used inside to abort the execution of further code at any point:

do {
    if (!condition1) break;
    some_code;
    if (!condition2) break;
    some_further_code;
    // …
} while(false);
Gumbo
  • 643,351
  • 109
  • 780
  • 844
2

I think this is done to use break or continue statements. Some kind of "goto" code logic.

Ivan Nevostruev
  • 28,143
  • 8
  • 66
  • 82
2

It's simple: Apparently you can jump out of the fake loop at any time using the break statement. Furthermore, the do block is a separate scope (which could also be achieved with { ... } only).

In such a situation, it might be a better idea to use RAII (objects automatically destructing correctly when the function ends). Another similar construct is the use of goto - yes, I know it's evil, but it can be used to have common cleanup code like so:

<return-type> function(<params>)
{
 <initialization>

 <main code for function using "goto error;" if something goes wrong>

 <tidy-up in success case & return>

 error:

 <commmon tidy-up actions for error case & return error code or throw exception>
}

(As an aside: The do-while-false construct is used in Lua to come up for the missing continue statement.)

AndiDog
  • 68,631
  • 21
  • 159
  • 205
2

How old was the author?

I ask because I once came across some real-time Fortran code that did that, back in the late 80's. It turns out that is a really good way to simulate threads on an OS that doesn't have them. You just put the entire program (your scheduler) in a loop, and call your "thread" routines" one by one. The thread routines themselves are loops that iterate until one of a number of conditions happen (often one being a certain amount of time has passed). It is "cooperative multitasking", in that it is up to the individual threads to give up the CPU every now and then so the others don't get starved. You can nest the looping subprogram calls to simulate thread priority bands.

T.E.D.
  • 44,016
  • 10
  • 73
  • 134
2

Many answerers gave the reason for do{(...)break;}while(false). I would like to complement the picture by yet another real-life example.

In the following code I had to set enumerator operation based on the address pointed to by data pointer. Because a switch-case can be used only on scalar types first I did it inefficiently this way

if (data == &array[o1])
    operation = O1;
else if (data == &array[o2])
    operation = O2;
else if (data == &array[on])
    operation = ON;

Log("operation:",operation);

But since Log() and the rest of code repeats for any chosen value of operation I was wandering how to skip the rest of comparisons when the address has been already discovered. And this is where do{(...)break;}while(false) comes in handy.

do {
    if (data == &array[o1]) {
        operation = O1;
        break;
    }
    if (data == &array[o2]) {
        operation = O2;
        break;
    }
    if (data == &array[on]) {
        operation = ON;
        break;
    }
} while (false);

Log("operation:",operation);

One may wonder why he couldn't do the same with break in an if statement, like:

if (data == &array[o1])
{
    operation = O1;
    break;
}
else if (...)

break interacts solely with the closest enclosing loop or switch, whether it be a for, while or do .. while type, so unfortunately that won't work.

Matt Bucci
  • 2,100
  • 2
  • 16
  • 22
4pie0
  • 29,204
  • 9
  • 82
  • 118
1

In addition to the already mentioned 'goto examples', the do ... while (0) idiom is sometimes used in a macro definition to provide for brackets in the definition and still have the compiler work with adding a semi colon to the end of a macro call.

http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/52f670f1292f30a4?tvc=2&q=while+(0)

Dan
  • 1,339
  • 3
  • 13
  • 19
0

The other reason I can think of is that it decorates the braces, whereas I believe in a newer C++ standard naked braces are not okay (ISO C doesn't like them). Otherwise to quiet a static analyzer like lint.

Not sure why you'd want them, maybe variable scope, or advantage with a debugger.

See Trivial Do While loop, and Braces are Good from C2.

To clarify my terminology (which I believe follows standard usage):

Naked braces:

init();
...
{
c = NULL;
mkwidget(&c);
finishwidget(&c);
}
shutdown();

Empty braces (NOP):

{}

e.g.

while (1)
   {}  /* Do nothing, endless loop */

Block:

if (finished)
{
     closewindows(&windows);
     freememory(&cache);
}

which would become

if (finished)
     closewindows(&windows);
freememory(&cache);

if the braces are removed, thus altering the flow of execution, not just the scope of local variables. Thus not 'freestanding' or 'naked'.

Naked braces or a block may be used to signify any section of code that might be a potential for an (inline) function that you wish to mark, but not refactor at that time.

mctylr
  • 5,159
  • 20
  • 32
  • Really? That's a shame. One of the few things I liked about C was that it let you declare a new nested scope just about anywhere. – T.E.D. Feb 22 '10 at 21:29
  • 1
    Naked braces are occasionally helpful to fix weird crashes. See http://blogs.msdn.com/oldnewthing/archive/2004/05/20/135841.aspx . – Brian Feb 22 '10 at 22:29
  • 1
    In C++, a block (i.e. your "naked braces") can be used anywhere a single statement would be allowed. – Ben Voigt May 02 '12 at 04:43
  • @BenVoigt Empty braces i.e. a NOP is different from a "naked braces" which is a block added around a linear sequence of instructions. E.g. ` printf("Hello"); { putchar(','); putchar(0x20); } printf("world!\n");` where the braces are **not** part of loop or branch control. – mctylr May 10 '12 at 15:08
  • @mctylr: I wasn't talking about empty braces. – Ben Voigt May 10 '12 at 19:55
  • @BenVoigt Okay, I believe that is normally considered a _block_, where the block replaces a single expression as-if the enclosed expressions were all typed on a single line. – mctylr Jun 13 '12 at 16:57
  • @Brain Yes, that is a good example case of scoping a local variable through (otherwise) naked braces. – mctylr Jun 13 '12 at 17:34
  • @mctylr: What you've called a *block*, is actually a conditional, where the *controlled-statement* is a block. But a block can be used anywhere a statement is allowed, not just as the *controlled-statement* of a conditional or loop. – Ben Voigt Jun 13 '12 at 17:54
  • @BenVoigt I did want to avoid making my examples complex, so I did avoid things like an expression with the comma operator, so I did use a example of a block (`statement` in C/C++ grammar terms) as the controlled statement of a conditional, but that block is equivalent to _compound_ statement or a single statement. Refs: C and C++ grammars, C Programming Language; The C++ Programming Language, Special edition I don't think newer editions redefine these basic definitions. – mctylr Jun 13 '12 at 18:23
0

It's a contrived way to emulate a GOTO as these two are practically identical:

// NOTE: This is discouraged!
do {
    if (someCondition) break;
    // some code be here
} while (false);
// more code be here

and:

// NOTE: This is discouraged, too!
if (someCondition) goto marker;
// some code be here
marker:
// more code be here

On the other hand, both of these should really be done with ifs:

if (!someCondition) {
    // some code be here
}
// more code be here

Although the nesting can get a bit ugly if you just turn a long string of forward-GOTOs into nested ifs. The real answer is proper refactoring, though, not imitating archaic language constructs.

If you were desperately trying to transliterate an algorithm with GOTOs in it, you could probably do it with this idiom. It's certainly non-standard and a good indicator that you're not adhering closely to the expected idioms of the language, though.

I'm not aware of any C-like language where do/while is an idiomatic solution for anything, actually.

You could probably refactor the whole mess into something more sensible to make it more idiomatic and much more readable.

Alan Plum
  • 10,814
  • 4
  • 40
  • 57
  • 1
    Alan, `do..while(false)` is *not* for running "undefined" number of times, it is for running *once*. – Dmitry Feb 22 '10 at 23:44
  • 2
    It is running an undefined number of times if you have a conditional `continue` statement at the end like I showed. By `undefined` I simply mean that you don't know whether it's running more than once unless you can predict whether the conditions will be met at a specific iteration. Without any `continue`s in it, `do..while(false)` will run once, but also without any `break`s in it, `while(true)` will run forever, so the "default behaviour" isn't really relevant to understand what _can_ be done with the loops. – Alan Plum Feb 23 '10 at 11:32
  • It's useful when you define a macro that has multiple statements. If you wrap them in a do / while(false) you can use the macro in an if/else statement like any other function call. see http://www.noveltheory.com/TechPapers/while.htm for an explanation – John Paquin Apr 25 '12 at 20:07
  • 5
    Someone doesn't understand the semantics of `continue`. `continue` does NOT repeat the loop. "The `continue` statement shall occur only in an *iteration-statement* and causes control to pass to the loop-continuation portion of the smallest enclosing *iteration-statement*, that is, to the end of the loop." – Ben Voigt May 02 '12 at 04:40
  • -1, the top two statements are not identical for the reasons that @BenVoigt points out. – cmh Aug 14 '13 at 10:59
  • @BenVoigt: Sorry about that. I have no idea how I missed the obvious condition evaluation step that would terminate the loop every time. I've removed the misleading example. – Alan Plum Sep 16 '13 at 16:27
  • nesting is indeed ugly, I'd prefer a goto. That being said, do { } while (false) seems like an interesting method that I hadn't previously considiered. – John Scipione Jun 25 '14 at 18:13
  • @JohnScipione Don't use goto if you want your stack to be cleaned up properly. Goto is a hard, assembly-level jump, so for example `__attribute(cleanup)` will not run on variables in a scope when you `goto` out. When you `break`, you cleanly leave the scope and stuff gets cleaned up. I thought the same went for C++ objects, but apparently C++ guarantees that they're cleaned up in that case. Though if I was in C++, I'd use exceptions instead of `goto` or `do{}while(false)` anyway. – uliwitness Jan 08 '17 at 23:02
0

I agree with most posters about the usage as a thinly disguised goto. Macros have also been mentioned as a potential motivation for writing code in the style.

I have also seen this construct used in mixed C/C++ environments as a poor man's exception. The "do {} while(false)" with a "break" can be used to skip to the end of the code block should something that would normally warrant an exception be encountered in the loop.

I have also sen this construct used in shops where the "single return per function" ideology is enforced. Again, this is in lieu of an explicit "goto" - but the motivation is to avoid multiple return points, not to "skip over" code and continue actual execution within that function.

Stan Graves
  • 6,795
  • 2
  • 18
  • 14
0

I work with Adobe InDesign SDK, and the InDesign SDK examples have almost every function written like this. It is due to fact that the function are usually really long. Where you need to do QueryInterface(...) to get anything from the application object model. So usually every QueryInterface is followed by if not went well, break.

Kugel
  • 19,354
  • 16
  • 71
  • 103
0

Many have already stated the similarity between this construct and a goto, and expressed a preference for the goto. Perhaps this person's background included an environment where goto's were strictly forbidden by coding guidelines?

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
0

Some coders prefer to only have a single exit/return from their functions. The use of a dummy do { .... } while(false); allows you to "break out" of the dummy loop once you've finished and still have a single return.

I'm a java coder, so my example would be something like

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class p45
{
    static List<String> cakeNames = Arrays.asList("schwarzwald torte", "princess", "icecream");
    static Set<Integer> forbidden = Stream.of(0, 2).collect(Collectors.toSet());

    public static  void main(String[] argv)
    {
        for (int i = 0; i < 4; i++)
        {
            System.out.println(String.format("cake(%d)=\"%s\"", i, describeCake(i)));
        }
    }


    static String describeCake(int typeOfCake)
    {
        String result = "unknown";
        do {
            // ensure type of cake is valid
            if (typeOfCake < 0 || typeOfCake >= cakeNames.size()) break;

            if (forbidden.contains(typeOfCake)) {
                result = "not for you!!";
                break;
            }

            result = cakeNames.get(typeOfCake);
        } while (false);
        return result;
    }
}
0

In such cases I use

switch(true) {
   case condution1:
      ...
      break;
   case condution2:
      ...
      break;
}
-2

This is amusing. There are probably breaks inside the loop as others have said. I would have done it this way :

while(true)
{
   <main code for function>
   break; // at the end.
}
fastcodejava
  • 39,895
  • 28
  • 133
  • 186
  • 3
    With a potential of looping forever? `do..while(false)` exits always, `while(true)` is more on a risky side. – Dmitry Feb 22 '10 at 21:44
  • 2
    `while(true)` is the correct idiom in most languages. You'll often find it in GUI applications as the program's main loop. Because you're basically assuming the program shouldn't die until it is told to do so, a `do..while(false)` would cause all sorts of contrived logic. This approach may be more risqué from a perfectionist POV, but it is semantically easier and thus less error prone for human programmers (sorry, Skynet). – Alan Plum Feb 22 '10 at 22:30
  • 2
    @dmitry `do{...}while(false)` is exactly same as `while(true){ .. break;}` – N 1.1 Mar 10 '10 at 09:18
  • 5
    @N1.1: Not in the presence of `continue`, they aren't the same. – Ben Voigt May 02 '12 at 04:42