swap(x,y)

Tom Karzes karzes at mfci.UUCP
Thu Sep 7 11:30:14 AEST 1989


In article <1989Sep6.061301.17629 at algor2.algorists.com> jeffrey at algor2.UUCP (Jeffrey Kegler) writes:
>One thing that makes
>
>A)   #define swap(x,y) (x ^= y, x ^= y ^= x)
>
>seem more attractive than
>
>B)   #define swap(x,y) {int tmp; tmp = x; y = tmp; x = y; }
>
>is the syntax.

Not to mention the fact that B) doesn't work.  Perhaps you meant:

    #define swap(x,y) {int tmp; tmp = x; x = y; y = tmp;}

One advantage of this over A) is that swap(a,a) works.  More realistically,
swap(a[i],a[j]) works when i == j.  Another advantage is that, though
amusing, A) is absurd, likely to be inefficient, and likely to inhibit
optimization.

As far as style goes:  When macros are written which should be thought of
as statements, then they should have the syntax of statements.  Yes, it's
a bit ugly, but a good naming convention will make it obvious that the macro
is in fact a macro.  The problem is that function references, which in many
contexts are thought of as statements, are really just expressions, and a
semicolon is needed to turn the expression into a statement.

If you want swap to be a statement with no defined result value, then
you should not be required to supply a semicolon to make it a statement.
Otherwise, if it is to be an expression with a defined value, then
it should be like any other expression and require a semicolon to
make it a statement.  Unfortunately, in this case you can't use a block
(i.e., a compound statement) because they aren't expressions in C and
hence cannot have result values.

>4) I think the idea of a global temporary to make Solution B an expression
>is unworkable if your global temporary has its name used elsewhere
>and ugly when it does work.

Well, I'll agree that it's a bit ugly, but it certainly isn't unworkable.
If you'll recheck the example, you'll see that the temporary is not
global, but is local to the block defined by the macro.  You therefore
only have to ensure that it doesn't conflict with any name used in x
or y.  This is easily accomplished by prefixing the name with some
prefix which is "owned" by the swap macro.  For example, if you call
the macro SWAP and designate any identifier beginning with SWAP_ as
being private to the swap macro, then you could use the following with
no risk of name conflict:

#define SWAP(x,y) {int SWAP_tmp; SWAP_tmp = x; x = y; y = SWAP_tmp;}

You could even make SWAP_tmp a global if you wanted, although this would
probably force your compiler to keep it in memory.



More information about the Comp.lang.c mailing list