4

I have compared gcc assembler output of

do { 

// some code 

} while (0);

with

do {
 
    // some code

    break; 
} while (1);

The output is equal, with or without optimization but..

It's always that way?

No experiment can prove theories, they can only show they are wrong

sigjuice
  • 28,661
  • 12
  • 68
  • 93
Hernán Eche
  • 6,529
  • 12
  • 51
  • 76
  • 15
    Why are you putting code into a while loop that doesn't loop? – jjnguy Jun 11 '10 at 14:50
  • Would you mind explaining why you would need to do that? In other words, what's the purpose of the do...while construct if you just wish to run the block of code once? – Amardeep AC9MF Jun 11 '10 at 14:53
  • 3
    The logic may be that under certain conditions a "continue" will be called, looping again. – sunside Jun 11 '10 at 14:53
  • 3
    It is a replacement for using goto's: break on exit-conditions. When refactoring, it pays to use extra functions instead and return when needed. – stefaanv Jun 11 '10 at 14:56
  • @Markus, if continue is called in a `do while` does the condition get checked before it loops again? – jjnguy Jun 11 '10 at 14:56
  • @jinguy - Absolutely. Continue causes the condition to be checked and if false the loop is aborted. – jmucchiello Jun 11 '10 at 14:58
  • 3
    Then, if continue is called in the loop, the behavior will be different. (@Markus, @jmucchiello) – jjnguy Jun 11 '10 at 15:00
  • 4
    `do { } while (0)` is a common idiom for writing Macros. It produces more compile errors than the alternatives, when used improperly... as for the `while (1)` with `break`... I have no idea why that would be useful. – Stephen Jun 11 '10 at 15:00
  • @jjnguy @Amardeep read to @stefaanv, that's the reason you can exit the block just with a break, it's a great way of make clean C code, for example testing many functions output and breaking whenever one of them return false, like a try-catch block without needing exceptions – Hernán Eche Jun 11 '10 at 15:02
  • 1
    do { } while ( false ) is a great way to not create huge if/else ladders. On error you break with a flag set. – Gregor Brandt Jun 11 '10 at 15:04
  • 1
    @Hernán Eche: The question is tagged C and C++. Which is it? If C++, then you have exceptions so you don't have to worry about doing without them. – CB Bailey Jun 11 '10 at 15:07
  • @Charles Bailey, you still can choose not to use exceptions, more in an embedded enviroment where resources are minimal. – Hernán Eche Jun 11 '10 at 15:10
  • @Hernán Eche: Personally, I don't buy the argument that exceptions are necessarily significantly more resource intensive than the alternative. I would (and do) buy the argument that some environment's support for exceptions is not robust or complete and this is found more often on embedded environments, but this means that your are coding with something less than C++. Anyway, you haven't answered my question. Are you asking about C or C++? – CB Bailey Jun 11 '10 at 15:16
  • @Charles Bailey, My question apply to both – Hernán Eche Jun 11 '10 at 15:18
  • 1
    @Hernán Eche: Your question might apply to both lanuages, but which are you actually asking about? It's obvious that some of the help that people are trying to provide depends on which you are actually asking about. – CB Bailey Jun 11 '10 at 15:21

6 Answers6

18

There is a slight difference:

do {
  // code
  if ( condition )
    continue;
  // code
  break;
} while(1);

Will restart the loop when condition is true, whereas in the } while(0); version, the continue will be equivalent to break.

If no continue is present, then they should produce exactly the same code.

Gianni
  • 4,300
  • 18
  • 24
  • 1
    Maybe they won't produce the same code, but they should do about the same thing. – zneak Jun 11 '10 at 15:07
  • can be always changed into something like: `do { /*code*/ } while(condition); /*code*/` at least, that specific example – ShinTakezou Jun 11 '10 at 15:45
  • @ShinTakezou Yes; the only practical reason might to use multiple conditions, and/or interlaced breaks. – Gianni Jun 11 '10 at 16:39
5

The forms are not equivalent. This is an infinite loop:

do {
    continue;
    break;
} while (1);

This isn't:

do {
    continue;
} while (0);
Sean
  • 29,130
  • 4
  • 80
  • 105
4

Edit: Upon reading various comments on the matter, I will admit that this answer is wrong. Sorry.

Instead of:

do{ 

//some code 

}while(0);

or:

do{

//some code

 break; 
}while(1);

I would just use:

//some code

I'm not 100% sure if you can do this in c++, but if you want to limit the scope of variables, and that is why you are doing this, just use curly braces by themselves:

{

 // Some Code

}
jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • What if you want to break or continue? – jmucchiello Jun 11 '10 at 14:58
  • No, I don't want to limit the scope, it's for using break inside the block and reach the end – Hernán Eche Jun 11 '10 at 15:00
  • 7
    @jmucchiello: Use a `goto`. No seriously. Using a fake loop so that you can disguise a `goto` as some other word is more evil than using `goto` in the first place. (IMHO) – CB Bailey Jun 11 '10 at 15:00
  • @jmucchiello I suppose I didn't consider that case. It seems to me that using other flow of control statements (if, then, else) would be more logical. But, then again, I don't think like a c programmer. – jjnguy Jun 11 '10 at 15:02
  • 1
    @Hernan If that is the case, then I think you should be using if/else blocks to achieve this. Or, even better, put the code into a method and use return to break out of the code early. Using a loop to do the job of if/else blocks seems broken to me. – jjnguy Jun 11 '10 at 15:03
  • @jjnguy: Why do you think this answer is wrong? It looks like a perfectly sensible answer to me. – CB Bailey Jun 11 '10 at 15:09
  • 1
    @Charles, The loop construct is being used for different reasons that what I thought when I first answered. It now makes perfect sense why someone would want to do this. (But, i still don't think it's a good idea) – jjnguy Jun 11 '10 at 15:12
  • 1
    @jinguy: The main use I've seen for `do { ... } while 0` is in macros, since it allows you to write a single statement that contains multiples. A block is not quite equivalent to a single statement, since `{ ... };` is two statements while `do { ... } while 0;` is one (and that can matter: consider `if (foo) bar(); else baz;`). This is mostly applicable in C, because C++ has better ways to write function-type macros. – David Thornley Jun 11 '10 at 15:16
  • @David Thornley: I fully agree that it's a "good" C macro solution (if you have to be writing function-style macros, but I don't think that that's the situation in the question. @jjnguy: I still think you are correct to suggest not using an actual loop where a loop isn't the logical construct required. – CB Bailey Jun 11 '10 at 15:19
4

Markus' comment pointed me to this answer: the difference is when using continue keyword.

In this case:

int _tmain(int argc, _TCHAR* argv[])
{
    int i = 0;
    do {
        ++i;
        _tprintf(_T("Iteration %d\n"), i);
        if (i < 30) continue;
    } while(0);

    return 0;
}

you get only one iteration, while in this case:

int _tmain(int argc, _TCHAR* argv[])
{
    int i = 0;
    do {
        ++i;
        _tprintf(_T("Iteration %d\n"), i);
        if (i < 30) continue;
        break;
    } while(1);

    return 0;
}

you get 30 iterations. Tested under VS2008.

Aoi Karasu
  • 3,730
  • 3
  • 37
  • 61
  • Karasu: I had to read this http://stackoverflow.com/questions/895827/what-is-the-difference-between-tmain-and-main-in-c to understand your code =P, yes that's the difference – Hernán Eche Jun 11 '10 at 16:03
  • @Hernán Eche: Sorry for the inconvenience. I use Microsoft's VS2008 for all my work :) – Aoi Karasu Jun 11 '10 at 16:23
3

The do while clauses are logically equivalent. If they are translated to the same byte code depends on the compiler at hand. I guess that most modern compilers will treat them equally.

kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
0

EDIT based on your comment that you're using a while with breaks in order to be able to break out of the 'loop' when certain conditions have been met.

If this is what you're trying to accomplish:

do
{ 
  // processing step 1
  if( some_condition )
    break;
  // processing step 2
  if( some_condition )
    break;
  // etcetera..
} while(0)

...then just break the code you have in your while loop out to a stand-alone function with multiple returns:

void processing()
{

  // processing step 1
  if( some_condition )
    return;
  // processing step 2
  if( some_condition )
    return;
  // etcetera..
}

int main()
{
  // ...
  processing();
  return 0;
}
John Dibling
  • 99,718
  • 31
  • 186
  • 324