[comp.lang.c] The nonexistent ^^ operator -- results

darren@revcan.UUCP (Darren Morbey) (04/15/91)

I would like to thank everyone who submitted responses to my question:

  How can one simulate -- portably -- a ^^ operator similar to && and ||?
  Also can it be guaranteed to execute both its operands once and only
  once (O&OO)?

I realize I should have been more specific about what I said and what
I knew (for example, && and || are, by definition, short-circuit, whereas
^^ could not be defined to do so.)  I did take a look at K&R I from the
Ottawa Public Library, so I understand more than I did when I asked.

Preliminary note:  Many of the responses involved "boolean normalization,"
  i.e. converting a numeric value to (int) 0 for any zero value and
  (int) 1 for any non-zero value.  (the casts are for clarity.)  There
  were essentially two different ways of doing this in the responses,
  and one could always be substituted for the other.  They were:
#define NORM(A)  !!(A)
#define NORM(A)  ((A) != 0)
  I use NORM(A) in the summary to mean either substitution may be used
  equally well.  You may choose to use NORM or "preprocess" directly.

And here are the responses and some comments:

     #define XOR(A,B)  ( !(A) && (B) || (A) && !(B) )
This was from the definition of the xor in Boolean algebra.  I said
this didn't work; I include it to appease those who didn't see it.
Like I said, there is a way for A to be executed twice and B not at
all.  I also discovered a similar way to have A and B both evaluate
twice.  I leave that only as a challenge.  It doesn't work; it fails
the O&OO requirement.

     #define XOR(A,B)  ( NORM(A) ^ NORM(B) )
This takes advantage that NORM(A) and NORM(B) are guaranteed 1 or 0.
A similar macro defines:
     #define XOR(A,B)  ( NORM(A) != NORM(B) )
Similarly, we may define:
     #define XOR(A,B)  ( !NORM(A) ^ !NORM(B) )
since A XOR B = (NOT A) XOR (NOT B).  If NORM(A) is !!(A), this is
     #define XOR(A,B)  ( !!!(A) ^ !!!(B) )
which abbreviates to
     #define XOR(A,B)  ( !(A) ^ !(B) )
Using != for ^ also produces the same results.

     #define XOR(A,B)  ( (A) ? !(B) : (B) )
This does ensure B to be evaluated O&OO.  In addition, it guarantees
that A is executed _before_ B (if that is a factor.)
It suffers: one response noted that B was substituted twice -- I
don't know whether there are optimizing compilers that only generate
code for B once (I don't think so, yet I cannot be sure.)
One response does note correctly that this macro cannot be guaranteed
(int) 0 or (int) 1, or for that matter, any int.  Use in an if() of
course doesn't matter, but storing the result of XOR could.  That
respondent does offer a solution to this problem, namely:
     #define XOR(A,B)  ( (A) ? !(B) : NORM(B) )

That basically covers all the solutions recieved by mail and news.
I thank you once again for your responses, and I leave you with the
following challenge (it may be no more than a mere exercise):
  given: #define XOR(A,B) ( !(A)&&(B) || (A)&&!(B) ) can you use it
  such that A is evaluated twice and B is evaluated:
  no times?  twice?

[ Darren Morby     +1 613 957 9281     {uunet|lsuc|fts1}!revcan!darren ]
[ Revenue Canada Taxation, 3052-400 Cumberland St, Ottawa,ONT  K1A 0L8 ]
[ "Under STRANGE MAMMALS we have the platypus for $100, the sloth      ]
[ for $150, and for $200, Pee-Wee Herman."                 -Dick Clark ]