[comp.std.c] macors and semicolons

andrew@otago.ac.nz (06/24/91)

I often get pissed off with the C pre-processor.  Here is one thats been
getting up my wick for months.

#define SWAP(a, b) {int c;  c = a; a = b; b = c}

if (spam)
   SWAP(a, b);
else
   a++;

These lines of code do a simple substitution

if (spam)
   {
   int c;
   c = a;
   a = b;
   b = c
   };
else
  a++;

notice the }; on the last line of the substitution.  This means that the else
is a syntax error!  With swap, there are a number of simple solutions...

#define SWAP(a, b) (b = (b ^ a) ^ (a = (b ^ a) ^ a))

simple hu?  but it only words with ints or longs. 

Question time....
how do I define a swap macro that swaps two doubles, allows the ';' on the end
of the macro call, but does not cause a systax error when used in this context?


Andrew
andrew@otago.ac.nz

raichle@azu.informatik.uni-stuttgart.de (Bernd Raichle) (06/24/91)

From FAQ(comp.lang.c):
Use #define SWAP(a, b) do{int c;  c = a; a = b; b = c}while(0)

-bernd

alanb@sdl.mdcbbs.com (06/24/91)

In article <1991Jun24.213932.595@otago.ac.nz>, andrew@otago.ac.nz writes:
> I often get pissed off with the C pre-processor.  Here is one thats been
> getting up my wick for months.
> 
> #define SWAP(a, b) {int c;  c = a; a = b; b = c}
> 
> if (spam)
>    SWAP(a, b);
> else
>    a++;
> 
> These lines of code do a simple substitution
> 
> if (spam)
>    {
>    int c;
>    c = a;
>    a = b;
>    b = c
>    };
> else
>   a++;
> 
> notice the }; on the last line of the substitution.  This means that the else
> is a syntax error!  With swap, there are a number of simple solutions...
> 
> #define SWAP(a, b) (b = (b ^ a) ^ (a = (b ^ a) ^ a))
> 
> simple hu?  but it only words with ints or longs. 
> 
> Question time....
> how do I define a swap macro that swaps two doubles, allows the ';' on the end
> of the macro call, but does not cause a systax error when used in this context?
> 
> 
> Andrew
> andrew@otago.ac.nz
> 

Use overloaded inline functions in C++
inline void swap (double &a, double &b) {double c; c = a; a = b; b = c;}
(unlikely to be an option, but (IMHO) the cleanest solution)

or
#define SWAP(a, b) do {double c;  c = a; a = b; b = c} while (false)

If you want the same macro to work with int or doubles
#define SWAP(type, a, b) do {type c;  c = a; a = b; b = c} while (false)

(And call 'c' something else unless you are sure you will never have a
macro argument that clashes with it e.g. use _m at the end of all variables
declared inside macros - makes life easier with a debugger too. But I assume
you just wanted nice short names for the illustration - reasonable.)

Some compilers will give you a warning about "while (false)". This is a good
sign - it proves they've worked out they don't need to put in any code to
implement the loop :-)

The other argument I've seen is if you use a macro, you should know about it
and not use the semi-colon. Personally I only like this argument for things
macros with unmatched braces, which couldn't be mistaken for (or replaced
with) a function.

alanb@sdl.mdcbbs.com   Alan Braggins
My opinions etc.

gwyn@smoke.brl.mil (Doug Gwyn) (06/24/91)

In article <1991Jun24.213932.595@otago.ac.nz> andrew@otago.ac.nz writes:
>#define SWAP(a, b) {int c;  c = a; a = b; b = c}
>how do I define a swap macro that swaps two doubles, allows the ';' on the end
>of the macro call, but does not cause a systax error when used in this context?

This is not a C standards question.

One obvious general solution is:
	#define MACRO(args) do { /*...*/ } while(0)

rob@meaddata.com (Robert E. Lancia) (06/25/91)

In article <1991Jun24.213932.595@otago.ac.nz> andrew@otago.ac.nz writes:
>I often get pissed off with the C pre-processor.  Here is one thats been
>getting up my wick for months.
>
>#define SWAP(a, b) {int c;  c = a; a = b; b = c}
                                               ^^

Notice that Andrew, as well as most of the replies I've seen so far,
forgot the semi-colon after the b=c assignment.

>
[ . . . stuff deleted . . . ]
>Andrew
>andrew@otago.ac.nz


Rob.
--
|Robert Lancia                 | The above opinions    | Mead Data Central
|(513) 297-2560                | may not necessarily   | Data Services Division
|rob@pmserv.meaddata.com       | be MDC's.  Heck, they | P.O. Box 308
|...!uunet!meaddata!pmserv!rob | may not even be mine. | Dayton, Ohio  45401