Page 1 of 1

do { ... } while(0); ?

Posted: Sun Dec 26, 2010 3:39 pm
by Dario
I came accross at this expression:

Code: Select all

#define ELF_PLAT_INIT(_r, load_addr)            \
        do {                                    \
        _r->bx = 0; _r->cx = 0; _r->dx = 0;     \
        _r->si = 0; _r->di = 0; _r->bp = 0;     \
        _r->ax = 0;                             \
} while (0)
at many places in Linux kernel. So why "while(0)"...I guess this is some programers practice that I never heard of.
The only reason for this expression, AFAIK, can be...I'm guessing optimization...dunno

____
Dario

Re: do { ... } while(0); ?

Posted: Sun Dec 26, 2010 4:13 pm
by gerryg400
It's not optimisation. It's used so that code like this will compile.

Code: Select all

if (....)
   ELF_PLAT_INIT(_r, load_addr);
else {
   ....
}
If the do {} while (0); weren't there you'd get (unexpectedly)

Code: Select all

if (....)
   {                                    \
        _r->bx = 0; _r->cx = 0; _r->dx = 0;     \
        _r->si = 0; _r->di = 0; _r->bp = 0;     \
        _r->ax = 0;                             \
   }
   ;
else {
   ....
}
That semicolon is a problem. Having the do {} while (0) fixes that. It makes the entire expanded macro a single statement.

Re: do { ... } while(0); ?

Posted: Sun Dec 26, 2010 4:18 pm
by Creature
I believe this has something to do with the use of if-statements and macro's. As you know, you can leave out the braces if there is only one expression:

Code: Select all

if(something)
   foo();

if(something)
{
   foo();
}
If you have more than one statement, you are forced to use braces. Macro's usually look like one function call, but they may instead expand to multiple statements and still need braces. Let's try that with macro's:

Code: Select all

#define Foo(x) { a = x; b = x; c = x; }

if(something)
   Foo(arg); // Wrong!
The above code will fail because there is a trailing semicolon ';' at the end after the braces. But if we do it this way:

Code: Select all

#define Foo(x) do { a = x; b = x; c = x; } while(0)

if(something)
   Foo(arg); // Works
The compiler is happy and it's not a syntax error to add the trailing semicolon. This article also explains it.

EDIT: gerryg400 beat me to it ;).

Re: do { ... } while(0); ?

Posted: Sun Dec 26, 2010 4:19 pm
by xenos
IIRC, the reason for this weird practice in #define's is to encapsulate the different assignments within a loop that is executed exactly once, so one may use the macro like a function. For example, with the code you posted, one can write:

Code: Select all

if(...)
    ELF_PLAT_INIT(_r, load_addr);
else
    some_other_function;
and it is expanded as

Code: Select all

if(...)
    do {...} while(0);
else
    some_other_function;
This would not work without the do...while(0) surrounding the different assignments, because that would be expanded as

Code: Select all

if(...)
    _r->bx = 0;

_r->cx = 0;
_r->dx = 0;
...
EDIT: That question was too simple, 3 answers in 6 minutes ;)

Re: do { ... } while(0); ?

Posted: Mon Dec 27, 2010 1:22 am
by Dario
It makes sense...I already see where I can apply that in my kernel code. 8)
Thanks!

Re: do { ... } while(0); ?

Posted: Fri Apr 27, 2012 10:39 am
by coreybrenner
There is a second reason for do { ... } while (0).

That second reason is: break