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

Programming, for all ages and all languages.
Post Reply
Dario
Member
Member
Posts: 117
Joined: Sun Aug 31, 2008 12:39 pm

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

Post 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
____
Dario
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

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

Post 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.
If a trainstation is where trains stop, what is a workstation ?
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

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

Post 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 ;).
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
xenos
Member
Member
Posts: 1118
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

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

Post 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 ;)
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Dario
Member
Member
Posts: 117
Joined: Sun Aug 31, 2008 12:39 pm

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

Post by Dario »

It makes sense...I already see where I can apply that in my kernel code. 8)
Thanks!
____
Dario
coreybrenner
Posts: 22
Joined: Thu Jul 15, 2010 11:47 pm

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

Post by coreybrenner »

There is a second reason for do { ... } while (0).

That second reason is: break
$ :(){ (:|:)& };:
Post Reply