[comp.lang.c] swap macro -- beware

devine@cookie.dec.com (Bob Devine) (01/20/88)

> #define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
> He [the genius] says it will work for anything (int, char *, etc.).

  Well, yes and no.  This old trick will work for those types that are
defined for the ^ op.  That means structs, arrays, unions, bitfields,
and floats won't work the way you want.  Something else that
will bite you if you use this macro is sign-extension, examine what
happens when swapping an int with a signed char whose top bit is on.
It may not result in what you thought it would.  The preprocessor
does not know C and does not follow type rules.

  The endless discussion of a generic swap macro some time ago
usually ended with the person bemoaning the lack of a "typeof()"
operator to handle the non-word-sized types.

exit(Bob) -- the unique and naturally refreshing choice for an exit value

jfh@killer.UUCP (John Haugh) (01/26/88)

In article <8801200422.AA19420@decwrl.dec.com>, devine@cookie.dec.com (Bob Devine) writes:
> > #define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))
> > He [the genius] says it will work for anything (int, char *, etc.).
> 
>   Well, yes and no.  This old trick will work for those types that are
> defined for the ^ op.  That means structs, arrays, unions, bitfields,
> and floats won't work the way you want.
> --
> exit(Bob) -- the unique and naturally refreshing choice for an exit value

This is a so old.  I thought this was taught as the way _not_ to swap
things.  I learned the original in Pascal as an undergrad.

Consider, what happens if A and B are both aliases for the same thing.
Given that order of evaluation is not guaranteed, can you find and order
of evaluation that this macro won't work for?

To bring in a conversation from a different thread, consider:

	a ^= b;
	b ^= a;
	a ^= b;	[ I think this was the code in that article ]

What if, A and B are aliases?

	let's say, A = B = 7.
	after a ^= b, both a and b == 0.
	then, after both b ^= a and a ^= b (the second time), a and b
	are STILL == 0.

If you assume the parenthesis are honored (and why not?),
#define swap(a,b) ((a) = ((b) = ((a) = (a) ^ (b)) ^ (b)) ^ (a))

	swap (X, X);

becomes

	X = X ^ X;
	X = X ^ X;
	X = X ^ X;

(which is the same as the above example)
which also doesn't work.

- John.
-- 
John F. Haugh II                  SNAIL:  HECI Exploration Co. Inc.
UUCP: ...!ihnp4!killer!jfh                11910 Greenville Ave, Suite 600
"Don't Have an Oil Well? ...              Dallas, TX. 75243
 ... Then Buy One!"                       (214) 231-0993 Ext 260