Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help understanding this use of while

9 views
Skip to first unread message

Chris Saunders

unread,
Mar 19, 2009, 10:15:12 PM3/19/09
to
I saw this code and don't understand this use of while. It seems to me
that the while loop will just occur once but then why use a while loop
at all? Here's the code:

#define SWAP_PTRS(x_dummy_p, y_dummy_p) \
do { \
fmpz_t swap_temp_p = x_dummy_p; \
x_dummy_p = y_dummy_p; \
y_dummy_p = swap_temp_p; \
} while(0);

Regards
Chris Saunders

pete

unread,
Mar 19, 2009, 10:34:40 PM3/19/09
to

The usual way to write to do{}while(0) loop macro,
is without the semicolon.

Then it would mean the same thing as:

#define SWAP_PTRS(x_dummy_p, y_dummy_p) \


{ \
fmpz_t swap_temp_p = x_dummy_p; \
x_dummy_p = y_dummy_p; \
y_dummy_p = swap_temp_p; \
}

does, except that it would require a terminating semicolon.

--
pete

Barry Schwarz

unread,
Mar 19, 2009, 11:51:47 PM3/19/09
to

It allows you to generate constructs such as
if (x) SWAP_PTRS(y,z)

Think about what would happen if the macro did not contain the "do"
and "while" lines.

--
Remove del for email

Ben Bacarisse

unread,
Mar 20, 2009, 12:10:33 AM3/20/09
to
Chris Saunders <ev...@mountaincable.net> writes:

It is (as pete has pointed out) a mistake. The usual case is without
the final ;. The logic goes like this:

You want a macro that has a declaration. You need a block for that.
If you write this:

#define SWAP(a,b) { T t=a; a=b; b=t; } /* ()s omitted for clarity */

then things go wrong if you write:

if (C)
SWAP(x, y);
else something_else();

Expand SWAP and look closely and you will see am empty statement
before the else. This is not valid syntax. So, what construct in C
has a block but can have a trailing ; and still remain a single
statement? Ah:

#define SWAP(a,b) do { T t=a; a=b; b=t; } while (0)

Now SWAP(x,y); is a correct, single statement.

If you don't omit the trailing ; from the macro, you might as well
just use a plain block and avoid the odd looking do ... while (0).

--
Ben.

Keith Thompson

unread,
Mar 20, 2009, 1:58:16 AM3/20/09
to

This is question 10.4 of the comp.lang.c FAQ, <http://www.c-faq.com/>.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

George Peter Staplin

unread,
Mar 20, 2009, 3:06:48 AM3/20/09
to
pete wrote:

A working do {} while(0) is not the same as that latter example you gave.

Consider this simple example:
#include <stdio.h>
#include <stdlib.h>

#define FOOINCR(x,y) { x += y; }

int main() {
int r = 0;

if(1)
FOOINCR(r, 2);
else
puts("BAR");

printf("r %d\n", r);

return EXIT_SUCCESS;
}

which becomes this from cpp:

int main() {
int r = 0;

if(1)
{ r += 2; };
else
puts("BAR");

printf("r %d\n", r);

return 0;
}

trying to build it results in:
error: expected expression before ‘else’


A do {} while(0) solves this problem. Observe:

#define FOOINCR(x,y) do { x += y; } while(0)

Now cpp produces this correct code:
int main() {
int r = 0;

if(1)
do { r += 2; } while(0);
else
puts("BAR");

printf("r %d\n", r);

return 0;
}


-George

Ben Bacarisse

unread,
Mar 20, 2009, 8:57:24 AM3/20/09
to
Barry Schwarz <schw...@dqel.com> writes:

True, but if the author of the macro intended the user of it do the
above (i.e. to watch his of her semicolons like a hawk) then what is
the point of the 'do' and the 'while(0);' -- i.e. why not just use a
block? It would be simpler and raise fewer questions. The whole
point of the do ... while (0) trick is to introduce a block that is
just one semicolon short of a full statement.

--
Ben.

CBFalconer

unread,
Mar 20, 2009, 6:00:32 PM3/20/09
to

Leave off the final ';'. Then the macro acts normally in all code.
e.g.:

if (something) SWAP_PTRS(x, y);
else {
/* other code */
}

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.


Malcolm McLean

unread,
Mar 22, 2009, 4:13:33 PM3/22/09
to

"Chris Saunders" <ev...@mountaincable.net> wrote in message
C doesn't allow bare blocks. So if you have a multi-line macro, and a
controlling statement

eg

#define MYMACRO() printf("Hello");printf("World");
if(x == y)
MYMACRO();

"World" will be printed if x != y, which probably isn't what you want.

The do ... while(0) is a hack to get round that oversight. It works very
well.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

pete

unread,
Mar 22, 2009, 4:28:14 PM3/22/09
to
Malcolm McLean wrote:
>
> "Chris Saunders" <ev...@mountaincable.net> wrote in message
>> I saw this code and don't understand this use of while. It seems to
>> me that the while loop will just occur once but then why use a while
>> loop at all? Here's the code:
>>
>> #define SWAP_PTRS(x_dummy_p, y_dummy_p) \
>> do { \
>> fmpz_t swap_temp_p = x_dummy_p; \
>> x_dummy_p = y_dummy_p; \
>> y_dummy_p = swap_temp_p; \
>> } while(0);
>>
> C doesn't allow bare blocks.

What does that mean?

--
pete

Lew Pitcher

unread,
Mar 22, 2009, 4:29:20 PM3/22/09
to
On March 22, 2009 16:13, in comp.lang.c, Malcolm McLean
(regn...@btinternet.com) wrote:

>
> "Chris Saunders" <ev...@mountaincable.net> wrote in message
>>I saw this code and don't understand this use of while. It seems to me
>>that the while loop will just occur once but then why use a while loop at
>>all? Here's the code:
>>
>> #define SWAP_PTRS(x_dummy_p, y_dummy_p) \
>> do { \
>> fmpz_t swap_temp_p = x_dummy_p; \
>> x_dummy_p = y_dummy_p; \
>> y_dummy_p = swap_temp_p; \
>> } while(0);
>>
> C doesn't allow bare blocks.

Hmmmm.... what do you mean by that? Why doesn't a C "compound statement"
qualify as a "bare block"?


> So if you have a multi-line macro, and a
> controlling statement
>
> eg
>
> #define MYMACRO() printf("Hello");printf("World");
> if(x == y)
> MYMACRO();
>
> "World" will be printed if x != y, which probably isn't what you want.

OTOH, if the macro were


#define MYMACRO() { printf("Hello"); printf("World"); }

then
if (x==y)
MYMACRO();
would work as expected.

> The do ... while(0) is a hack to get round that oversight. It works very
> well.

I think that you really wanted to illustrate
if (x == y)
MYMACRO();
else
do_something_else();

If MYMACRO() expanded to a full statement (either a semi-colon terminated
single statement, or a brace bracketed compound statement), the trailing
semicolon from the unexpanded invocation (the semicolon at the end
of "MYMACRO();") would be taken as a new (empty) statement at the same
level as the "if" statement.

This, in turn, would "unpair" the following "else" statement from the "if"
statement, causing a syntax error upon compilation.

The "do { } while(0)" macro expansion takes advantage of the syntax of the
do/while verb, along with the behaviour of the while(0) condition, to
permit a single pass through the "do {} while()" logic (like the compound
statement would permit), while permitting (requiring) the macro invocation
to be treated as a single statement, terminated with a semicolon. Thus, the
semicolon that follows the MYMACRO() invocation is paired with the while()
clause of the expanded macro, and the "else" is left to be properly paired
with the preceding "if".

The drawback to using a "do {} while(0)" macro is that the invocation /must/
be terminated with a semicolon. This means that it is /not/ proper to use
this sort of macro as anything other than the rightmost rvalue of a
statement. In other words, you can't use it as
a = MYMACRO() + 6;
or even
a = MYMACRO(), 10;

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------


Phil Carmody

unread,
Mar 22, 2009, 4:48:00 PM3/22/09
to
"Malcolm McLean" <regn...@btinternet.com> writes:
> "Chris Saunders" <ev...@mountaincable.net> wrote in message
>> I saw this code and don't understand this use of while. It seems to
>> me that the while loop will just occur once but then why use a while
>> loop at all? Here's the code:
>>
>> #define SWAP_PTRS(x_dummy_p, y_dummy_p) \
>> do { \
>> fmpz_t swap_temp_p = x_dummy_p; \
>> x_dummy_p = y_dummy_p; \
>> y_dummy_p = swap_temp_p; \
>> } while(0);
>
> C doesn't allow bare blocks.

What's that supposed to mean?

#include <stdio.h>
int main()
{
{
int ImInABareBlock=1;
printf("He's in a bare block - %i", ImInABareBlock);
}
}

Quite how you'd like that bare block to be adorned in order
to be not allowed, I don't know, but I suspect it'd not be
sensibly called a bare block afterwards.

Phil
--
Marijuana is indeed a dangerous drug.
It causes governments to wage war against their own people.
-- Dave Seaman (sci.math, 19 Mar 2009)

pete

unread,
Mar 22, 2009, 5:27:04 PM3/22/09
to
Lew Pitcher wrote:

> The drawback to using a "do {} while(0)" macro is that the invocation /must/
> be terminated with a semicolon. This means that it is /not/ proper to use
> this sort of macro as anything other than the rightmost rvalue of a
> statement.

The "do{}while(0)" macro
may not be used as any kind of a value at all.

--
pete

0 new messages