[comp.lang.c] The nonexistent operator

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

I've noticed in my writing C code that there is no such operator
as ^^ (which would be to ^ as || is to |).  I feel in this case
I *have* to write a macro for this *nonexistent* operator (you may
recall I wrote #define XOR(a,b) ((a)^(b)) ).  However...

The Pascal xor operator is <>, which follows since it has a Boolean
type on which its and & or operators can (and only will) operate.
Since C uses any non-zero value as 'true', it seems the only reason
to include && and || to avoid trouble with & and |.  The problem is,
there is no ^^ to avoid trouble with ^.

I would like to use one of the following three macros, but each has
its own particular problems.  I would appreciate any advice on which
one should be used.  I would like it to operate like && and ||.

1.    #define XOR(a,b) ( ( !(a) && (b) ) || ( (a) && !(b) ) )
      - Althought this is straight from the definition of XOR
        ( as (NOT A AND B) OR (A AND NOT B) ) it must evaluate
        a and b *twice* (obvious loss of flexibility)

2.    #define XOR(a,b) ( !(a) != !(b) )
      - This is meant to overcome C's acceptance of multiple TRUEs
        ( unlike Pascal's single TRUE value ).  This relies on the
        following statements being true:
        ( 0 == 0L ) (since a and b may yield different sized int's)
        ( !0 == !(0L) )
        ( !(0L) == !('\0') ) (which may happen!)
        etc.  Can such expressions be *guaranteed* true?

3.    #define XOR(a,b) ( (a) ? !(b) : (b) )  /* my favourite. */
      - This relies simply on one thing: in the conditional expression,
        do *both* !(b) and (b) get evaluated, regardless of which is
        returned?  Or is only the value to be returned evaluated.
(Final note: This *is* meant to be *portable*.  Be very careful.)

[ Darren Morby     +1 613 957 9281     {uunet|lsuc|fts1}!revcan!darren ]
[ Revenue Canada Taxation, 3052-400 Cumberland St, Ottawa,ONT  K1A 0L8 ]
 (included for those who wish to send mail, call me, or send any lynch)
 (mobs you can hire. :-)                                              )

ckp@grebyn.com (Checkpoint Technologies) (04/03/91)

In article <156@revcan.UUCP> darren@revcan.UUCP (Darren Morbey) writes:
>I've noticed in my writing C code that there is no such operator
>as ^^ (which would be to ^ as || is to |).  I feel in this case
>I *have* to write a macro for this *nonexistent* operator (you may
>recall I wrote #define XOR(a,b) ((a)^(b)) ).  However...
>
>I would like to use one of the following three macros, but each has
>its own particular problems.  I would appreciate any advice on which
>one should be used.  I would like it to operate like && and ||.

An ^^ operator cannot operate just like && and ||.  This is because
there is no possible notion of a shortcut evaluation; both sides must be
evaluated in every case.

I'll assume you mean for ^^ to operate on operands which are only
treated as 0 or non-0, and returns either 0 or 1.

>1.    #define XOR(a,b) ( ( !(a) && (b) ) || ( (a) && !(b) ) )
>2.    #define XOR(a,b) ( !(a) != !(b) )
>3.    #define XOR(a,b) ( (a) ? !(b) : (b) )  /* my favourite. */

Here's mine:

#define XOR(a,b) (((a) != 0) ^ ((b) != 0))

-- 
First comes the logo: C H E C K P O I N T  T E C H N O L O G I E S      / /  
                                                ckp@grebyn.com      \\ / /    
Then, the disclaimer:  All expressed opinions are, indeed, opinions. \  / o
Now for the witty part:    I'm pink, therefore, I'm spam!             \/

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

Based on some of the responses I've gotten so far, I should
clarify what I would like when I say ^^.  I do realize that there
is no "short-circuit" evaluation (a term used repeatedly) for the
Boolean xor as there is for && and ||; I didn't realize that
short-circuit evaluation was the standard.

What I did require was an operator, macro, or function that treated
its operands as "zero" or "non-zero" as && and || do rather than
the bitwise & | ^.  I also would like some guarantee that both
operands were evaluated *once* *and* *only* *once* (O&OO).  Based
on that, I do recognize that in
  1.    #define XOR(a,b) ( ( !(a) && (b) ) || ( (a) && !(b) ) )
I cannot guarantee that a is evaluated O&OO every time.

As I mentioned, I would like to be as portable as possible, so
please be careful.

[ Darren Morby     +1 613 957 9281     {uunet|lsuc|fts1}!revcan!darren ]
[ Revenue Canada Taxation, 3052-400 Cumberland St, Ottawa,ONT  K1A 0L8 ]
[                            "The challenge... is yours."  Dick Clark. ]

barnettr@snaggle.rtp.dg.com (Richard Barnette) (04/04/91)

In article <156@revcan.UUCP> darren@revcan.UUCP (Darren Morbey) writes:
>I've noticed in my writing C code that there is no such operator
>as ^^ (which would be to ^ as || is to |).  I feel in this case
>I *have* to write a macro for this *nonexistent* operator (you may
>recall I wrote #define XOR(a,b) ((a)^(b)) ).  However...

    It can't be done.  The truth or falseness of a ^ expression
cannot be determined without evaluating all the operands.  Note
the truth tables below:

    A B | A XOR B    A B | A AND B    A B | A AND B
   -----+---------  -----+---------  -----+---------
    F F |    F       F F |    F       F F |    F   
    F T |    T       F T |    T       F T |    F   
    T F |    T       T F |    T       T F |    F   
    T T |    F       T T |    T       T T |    T    

    Given A if F, A AND B is always F; given A is T, A OR B is always
T.  No such statement can be made for A XOR B;  if A is T, A XOR B is
NOT B; if A is F, A XOR B is B.  In either case the value depends on
B regardless of the value of A.

-------------------------------------------------------
Richard Barnette       |   Data General Corporation
Commercial Languages   |   62 T.W. Alexander Drive
(919) 248-6225         |   RTP, NC  27709
-------------------------------------------------------
Inet addr:  barnettr@dg-rtp.dg.com
UUCP:  <your 'world' string here>!mcnc!rti!dg-rtp!barnettr
-------------------------------------------------------
obligatory (in)famous quote:
  "You wascal wabbit!  Wandering wizards won't win!"
     - /usr/lib/sendmail
    /-------------------------------------------------------\
    | Richard Barnette       |   Data General Corporation   |
    | Commercial Languages   |   62 T.W. Alexander Drive    |
    | x 6225                 |   RTP, NC  27709             |

dkeisen@Gang-of-Four.Stanford.EDU (Dave Eisen) (04/04/91)

In article <157@revcan.UUCP> darren@revcan.UUCP (Darren Morbey) writes:
>What I did require was an operator, macro, or function that treated
>its operands as "zero" or "non-zero" as && and || do rather than
>the bitwise & | ^.  I also would like some guarantee that both
>operands were evaluated *once* *and* *only* *once* (O&OO).  Based
>on that, I do recognize that in

#define XOR(a,b)	(!!(a) ^ !!(b))

does what you want.




--
Dave Eisen                      
1101 San Antonio Rd. Suite 102    
Mountain View, CA 94043                   
(415) 967-5644                   dkeisen@Gang-of-Four.Stanford.EDU (for now)

jlg@cochiti.lanl.gov (Jim Giles) (04/05/91)

> [...]
>   It can't be done.  The truth or falseness of a ^ expression
> cannot be determined without evaluating all the operands. [...]

What you are saying is obvious.  However, the original request
was for a _logical_ XOR instead of a _bit-wise_ XOR.  The fact
that you can't short-circuit XOR is irrelevant to that request.

This is one of the problems with confounding two distinct concepts
into one language feature - people soon begin to believe the two
concepts are inseparable.  In this case, short-circuiting and 
logical con/disjunction are distinct concepts that just happen
to be combined into single operators.

J. Giles

gwyn@smoke.brl.mil (Doug Gwyn) (04/05/91)

In article <1991Apr3.203748.3226@neon.Stanford.EDU> dkeisen@Gang-of-Four.Stanford.EDU (Dave Eisen) writes:
>#define XOR(a,b)	(!!(a) ^ !!(b))

or even
#define XOR(a,b) (!(a)^!(b))
which is, I think, the shortest fully correct solution to this
rather peculiar "requirement".

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/05/91)

In article <20206@lanl.gov> jlg@cochiti.lanl.gov (Jim Giles) writes:
> This is one of the problems with confounding two distinct concepts
> into one language feature - people soon begin to believe the two
> concepts are inseparable.  In this case, short-circuiting and 
> logical con/disjunction are distinct concepts that just happen
> to be combined into single operators.

What Jim fails to point out is that short-circuiting is almost entirely
useless with bitwise operators---it could only make a difference if the
first argument had all bits zero, and you can use (a)?(b):0 for that.

Conversely, since you can always implement a non-short-circuit logical
operator as (e.g.) !!(a) & !!(b), there's no reason for the language to
provide any logical operators other than the short-circuit ones.

This is common sense, not ``confounding.''

---Dan

rh@smds.UUCP (Richard Harter) (04/05/91)

In article <157@revcan.UUCP>, darren@revcan.UUCP (Darren Morbey) writes:

> What I did require was an operator, macro, or function that treated
> its operands as "zero" or "non-zero" as && and || do rather than
> the bitwise & | ^.  I also would like some guarantee that both
> operands were evaluated *once* *and* *only* *once* (O&OO)...

Then I believe that what you want is

#define XOR(a,b) (  !(a)  ?  (!!(b))  :  (!(b))  )

which returns 1 if exactly one of the two arguments is 0 and 0 otherwise,
with both arguments being evaluated exactly once.  As far as I can see this
is the only way to meet your requirements.  I am not at all sure if it is
possible to write macros for AND and OR that meet your requirements.  The
problem I see is this:

#define AND(a,b)  ( !(a) ? ((b) && 0) : !!(b)  )

appears to do the trick, modulo typoes.  However it occurs to me that a
"clever" optimizing compiler would recognize that ((b) && 0 ) is always
false and bypass the evaluation of b.  Perhaps the language lawyers can
tell us if the language specifications *require* that b be evaluated.

-- 
Richard Harter, Software Maintenance and Development Systems, Inc.
Net address: jjmhome!smds!rh Phone: 508-369-7398 
US Mail: SMDS Inc., PO Box 555, Concord MA 01742
This sentence no verb.  This sentence short.  This signature done.

kers@hplb.hpl.hp.com (Chris Dollin) (04/05/91)

Dave Eisen writes (apropos of the ``xor'' discussion):

   #define XOR(a,b)	(!!(a) ^ !!(b))
   does what you want.

Hmm ... we can strip one of the !'s from each pair to get

    (!(a) ^ !(b))

If the XOR is likely to be used in conditional contexts (rather than value
contexts) then I'd guess that more compilers could optimise equality tests than
^ instructions (because more machines have some sort of branch-if-(n)eq), so
how about

#define XOR(a,b)   (!(a) != !(b))


--

Regards, Kers.      | "You're better off  not dreaming of  the things to come;
Caravan:            | Dreams  are always ending  far too soon."

Sepp@ppcger.ppc.sub.org (Josef Wolf) (04/06/91)

darren@revcan.UUCP (Darren Morbey) writes:

] 1.    #define XOR(a,b) ( ( !(a) && (b) ) || ( (a) && !(b) ) )
] 2.    #define XOR(a,b) ( !(a) != !(b) )
] 3.    #define XOR(a,b) ( (a) ? !(b) : (b) )  /* my favourite. */

Waht about #define XOR(a,b) (a) != (b) /* just a suggestion */

Greets
    Sepp

| Josef Wolf, Germersheim, Germany | +49 7274 8047  -24 Hours- (call me :-)
| ...!ira.uka.de!smurf!ppcger!sepp | +49 7274 8048  -24 Hours-
|     sepp@ppcger.ppc.sub.org      | +49 7274 8967  18:00-8:00, Sa + Su 24h
|  "is there anybody out there?"   | all lines 300/1200/2400 bps 8n1

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/07/91)

In article <372@smds.UUCP> rh@smds.UUCP (Richard Harter) writes:
> #define AND(a,b)  ( !(a) ? ((b) && 0) : !!(b)  )
> appears to do the trick, modulo typoes.  However it occurs to me that a
> "clever" optimizing compiler would recognize that ((b) && 0 ) is always
> false and bypass the evaluation of b.  Perhaps the language lawyers can
> tell us if the language specifications *require* that b be evaluated.

I'm not much of a language lawyer, but yes, b is evaluated once.

---Dan

volpe@camelback.crd.ge.com (Christopher R Volpe) (04/08/91)

In article <NSfh-D@ppcger.ppc.sub.org>, Sepp@ppcger.ppc.sub.org (Josef
Wolf) writes:
|>Waht about #define XOR(a,b) (a) != (b) /* just a suggestion */

If a==5 and b==6, do you want XOR(a,b)==1??

|>| Josef Wolf, Germersheim, Germany | +49 7274 8047  -24 Hours- (call me :-)
|>| ...!ira.uka.de!smurf!ppcger!sepp | +49 7274 8048  -24 Hours-
|>|     sepp@ppcger.ppc.sub.org      | +49 7274 8967  18:00-8:00, Sa + Su 24h
|>|  "is there anybody out there?"   | all lines 300/1200/2400 bps 8n1
               
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

alan@ukpoit.co.uk (Alan Barclay) (04/11/91)

In article <1991Apr3.184316.11559@dg-rtp.dg.com> barnettr@snaggle.rtp.dg.com (Richard Barnette) writes:
>
>    A B | A XOR B    A B | A AND B    A B | A AND B
>   -----+---------  -----+---------  -----+---------
>    F F |    F       F F |    F       F F |    F   
>    F T |    T       F T |    T       F T |    F   
>    T F |    T       T F |    T       T F |    F   
>    T T |    F       T T |    T       T T |    T    
>
>    Given A if F, A AND B is always F; given A is T, A OR B is always
>T.  No such statement can be made for A XOR B;  if A is T, A XOR B is

I take it that the A AND B table should read F,F,T,T as F AND T is F.
-- 
  Alan Barclay
  iT                                |        E-mail : alan@ukpoit.uucp
  Barker Lane                       |        BANG-STYLE : .....!ukc!ukpoit!alan
  CHESTERFIELD S40 1DY              |        VOICE : +44 246 214241

jhz@cunixa.cc.columbia.edu (Jennifer H. Zemsky) (04/14/91)

In article <1991Apr11.122102.5976@ukpoit.co.uk> alan@ukpoit.co.uk (Alan Barclay) writes:
>In article <1991Apr3.184316.11559@dg-rtp.dg.com> barnettr@snaggle.rtp.dg.com (Richard Barnette) writes:
>>
>>    A B | A XOR B    A B | A AND B    A B | A AND B
>>   -----+---------  -----+---------  -----+---------
>>    F F |    F       F F |    F       F F |    F   
>>    F T |    T       F T |    T       F T |    F   
>>    T F |    T       T F |    T       T F |    F   
>>    T T |    F       T T |    T       T T |    T    
>>
>
>I take it that the A AND B table should read F,F,T,T as F AND T is F.
>-- 
>  Alan Barclay

either i missed this statement:
#define humor 1

or you really didn't recognize the middle table as A OR B, since T AND F is
also F.

--jhz

sorry, no funny sig.  maybe later.