[comp.lang.c] Efficient swap

heal@ux1.cso.uiuc.edu (Loren Heal) (01/13/91)

-----------------
Here is a one-line C macro, swap():  The principle is well-known, 
but I've never seen it done this tersely:

#define swap(A,B) (A^=B^=A^=B)

I admit that's not too readable.  It works for integer-compatible 
types, on the principles of the exclusive-OR operation.  Working 
from right to left, First A is xor'd with B, so that A is now A^B, 
B is still B.  Then B is xor'd with the A^B, which leaves the 
original value of A in B.  Then finally A (which is A^B) is xor'd 
with the original value of A, so that A contains the original 
value of B.  I usually use the alternative form

#define sort2(A,B) ((A>=B)?0:((A^=(B^=(A^=B))),1))

Loren Heal, heal@ux1.cso.uiuc.edu, *net!uiucuxc!ux1!heal.
-- 
*----------------------------------------------------------------------*
: Loren E. Heal : leheal@uiuc.edu (from *net, you figure it out)       :
:(Not a spokesman for the University of Illinois at Urbana-Champaign)  :
:(I may work there, but I still own my own mind!)                      :

bengsig@oracle.nl (Bjorn Engsig) (01/14/91)

Article <1991Jan13.050236.11634@ux1.cso.uiuc.edu> by heal@ux1.cso.uiuc.edu (Loren Heal) says:
|#define swap(A,B) (A^=B^=A^=B)
Maybe you should have read the list of Frequently Asked Questions before
posting this.
-- 
Bjorn Engsig,         E-mail: bengsig@oracle.com, bengsig@oracle.nl
ORACLE Corporation    Path:   uunet!orcenl!bengsig

            "Stepping in others footsteps, doesn't bring you ahead"

volpe@camelback.crd.ge.com (Christopher R Volpe) (01/14/91)

In article <1991Jan13.050236.11634@ux1.cso.uiuc.edu>,
heal@ux1.cso.uiuc.edu (Loren Heal) writes:
|>
|>-----------------
|>Here is a one-line C macro, swap():  The principle is well-known, 
|>but I've never seen it done this tersely:
|>
|>#define swap(A,B) (A^=B^=A^=B)

This is not legal C. (I mean using this macro is not legal. The
definition itself is fine.) It assumes that the assignments to the
variables occur during (or somehow in sync with) the evaluation of
each "^=" operator. They don't. The assignments occur sometime between
the previous and next sequence points (3.3.16). There are two assignments
to variable "A" in that expression. It's certainly possible that the
assignment corresponding to the rightmost assignment operator can
take place AFTER the assignment corresponding to the leftmost operator,
giving you garbage results. 

Section F.2 identifies the following as an example of a circumstance in
which the behavior is undefined: "An object is modified more than once, or
is modified and accessed other than to determine the new value, between
sequence points."

|>Loren Heal, heal@ux1.cso.uiuc.edu, *net!uiucuxc!ux1!heal.
|>-- 
|>*----------------------------------------------------------------------*
|>: Loren E. Heal : leheal@uiuc.edu (from *net, you figure it out)       :
|>:(Not a spokesman for the University of Illinois at Urbana-Champaign)  :
|>:(I may work there, but I still own my own mind!)                      :
                       
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

henry@zoo.toronto.edu (Henry Spencer) (01/27/91)

In article <1991Jan13.050236.11634@ux1.cso.uiuc.edu> heal@ux1.cso.uiuc.edu (Loren Heal) writes:
>Here is a one-line C macro, swap()...

This comes up every few months.  See the Frequently-Asked-Questions list.

It's both unsafe and inefficient, by the way, and as an art form it lacks
charm.  Especially on the tenth repetition.  Is there some special reason
why you posted it?
-- 
If the Space Shuttle was the answer,   | Henry Spencer at U of Toronto Zoology
what was the question?                 |  henry@zoo.toronto.edu   utzoo!henry