Why isn't there a logical XOR operator?

  • Thread starter Christopher Benson-Manica
  • Start date
K

Kevin D. Quitt

Are you still convinced that it would be useful?

Yes, for the same reason as || and &&, albeit there's no shortcutting. It
makes it *obvious* that a purely boolean expression is involved. !a ^ !b
isn't obviously purely boolean; the central operator is not boolean.
 
A

Arthur J. O'Dwyer

Christopher Benson-Manica writes:
[re: introducing a logical XOR operator]
Because ^ is good enough, given the fact that a logical XOR operator
couldn't have any shortcircuiting semantics. !a ^ !b yields exactly
the same result as the hypothetical ^^ operator.

Possibly dumb, and possibly OT, question: What if 'a' and/or 'b' are
doubles with the IEEE value NaN, that screws up comparisons? Does
If a and b are already
logical expressions (i.e. expressions that evaluate to 0 or 1), a ^ b is
enough.


Are you still convinced that it would be useful?

Well, a logical xor operator wouldn't add anything to the capabilities
of the language, but then neither does having a special operator for
subtraction. I have, on occasion, run across situations where an XOR
operator would have been useful. Christopher mentioned command-line
argument parsing, such as:

[...]
switch (argv[j]) {
case 'K': KNRStyle = 1; break;
case 'A': AnsiStyle = 1; break;
}
[...]
if (KNRStyle ^^ AnsiStyle)
process(infp, outfp);
else
do_error("You must specify exactly one of -K, -A!\n");

Here the ^^ operator would capture the spirit of the condition better
than the != alternative, as well as being slightly more robust. The
suggested alternative,

if (!KNRStyle != !AnsiStyle)

is IMO so obfuscated as to be actually worse than simply enumerating
the cases:

if (KNRStyle && !AnsiStyle || AnsiStyle && !KNRStyle)


I also submit for consideration, as I've done before, the usefulness
of logical operators when dealing with pointers:

struct btnode {
int value;
struct btnode *left;
struct btnode *right;
};

int bt_IsUselessBranch(struct btnode *p)
{
return (p->value == 0) && (p->left ^^ p->right);
}

versus

return (p->value == 0) && (!(p->left) != !(p->right));

Of course, both cases are pretty ugly, here. But I haven't yet
come up with a good example. ;-)
And while I think it would have been cool if C had been designed
with a ^^ operator from the start, IMHO it's much too late now to
try adding it to the standard language. C doesn't need any more
syntax, and even if it did, I don't think the new syntax would find
many willing users. A new version of C would IMHO suffer the same
problems as C99 still suffers w.r.t. market share, only worse.
Now, a *new* language... :)

-Arthur
 
?

=?iso-8859-1?q?Jos=E9_de_Paula?=

Em Tue, 03 Feb 2004 17:05:14 +0000, CBFalconer escreveu:
Christopher Benson-Manica wrote:
if (!!a ^ !!b) ....

c = !!a ^ !!b;

Why !!a ? Doesn't this have the same effect of a? Like
if (a ^ b) ....
c = a ^ b;

Could you enlighten us?
 
A

Arthur J. O'Dwyer

Em Tue, 03 Feb 2004 17:05:14 +0000, CBFalconer escreveu:


Why !!a ? Doesn't this have the same effect of a? Like
if (a ^ b) ....
c = a ^ b;

Could you enlighten us?

What is the value of 42?
What is the value of !!42?
What is the value of 42 ^ 6?
What is the value of !!42 ^ !!6?

-Arthur,
rhetorically
 
L

Lew Pitcher

José de Paula said:
Em Tue, 03 Feb 2004 17:05:14 +0000, CBFalconer escreveu:






Why !!a ? Doesn't this have the same effect of a? Like
if (a ^ b) ....
c = a ^ b;

Could you enlighten us?


Assume
a = 2;
b = 7;

Then
a ^ b == 2 ^ 7
== 5

which evaluates false in an if() statement

However
!a == 0

!!a == ! (!a)
== 1

!b == 0

!!b == ! (!b)
== 1

!!a ^ !!b == 1 ^ 1
== 0

which evaluates true in an if() statement
 
J

Joona I Palaste

José de Paula said:
Em Tue, 03 Feb 2004 17:05:14 +0000, CBFalconer escreveu:
Why !!a ? Doesn't this have the same effect of a? Like
if (a ^ b) ....
c = a ^ b;
Could you enlighten us?

No, it's not the same effect. The outcome is mostly the same, but
there are differences.
Suppose a is 1 and b is 2. a ^ b will now be 3, which is different
from 0, and thus C considers it true.
However !!a will be 1, and !!b will also be 1, so !!a ^ !!b will be
0, and thus C considers it false.
The ! operator is defined as returning 1 if its operand is 0, or
returning 0 if its operand is anything other. !! is two ! operators
together, they return 0 if their operand is 0, or 1 if their operand
is anything other.
This is often used as a neat trick to "force" non-zero values to 1,
making sure bitwise operators work right in place of logical operators.
 
L

Lew Pitcher

Gak!! Another fingercheck/brainfart

Lew said:
Assume
a = 2;
b = 7;

Then
a ^ b == 2 ^ 7
== 5

which evaluates false in an if() statement
which evaluates /true/ in an if() statement
However
!a == 0

!!a == ! (!a)
== 1

!b == 0

!!b == ! (!b)
== 1

!!a ^ !!b == 1 ^ 1
== 0

which evaluates true in an if() statement
which evaluates /false/ in an if() statement
 
P

pete

Arthur said:
Christopher Benson-Manica writes:
[re: introducing a logical XOR operator]
Because ^ is good enough, given the fact that a logical XOR operator
couldn't have any shortcircuiting semantics. !a ^ !b yields exactly
the same result as the hypothetical ^^ operator.

Possibly dumb, and possibly OT, question: What if 'a' and/or 'b' are
doubles with the IEEE value NaN, that screws up comparisons? Does
If a and b are already
logical expressions (i.e. expressions that evaluate to 0 or 1), a ^ b is
enough.


Are you still convinced that it would be useful?

Well, a logical xor operator wouldn't add anything to the capabilities
of the language, but then neither does having a special operator for
subtraction. I have, on occasion, run across situations where an XOR
operator would have been useful. Christopher mentioned command-line
argument parsing, such as:

[...]
switch (argv[j]) {
case 'K': KNRStyle = 1; break;
case 'A': AnsiStyle = 1; break;
}
[...]
if (KNRStyle ^^ AnsiStyle)
process(infp, outfp);
else
do_error("You must specify exactly one of -K, -A!\n");

Here the ^^ operator would capture the spirit of the condition better
than the != alternative, as well as being slightly more robust. The
suggested alternative,

if (!KNRStyle != !AnsiStyle)

is IMO so obfuscated as to be actually worse than simply enumerating
the cases:

if (KNRStyle && !AnsiStyle || AnsiStyle && !KNRStyle)

I also submit for consideration, as I've done before, the usefulness
of logical operators when dealing with pointers:

struct btnode {
int value;
struct btnode *left;
struct btnode *right;
};

int bt_IsUselessBranch(struct btnode *p)
{
return (p->value == 0) && (p->left ^^ p->right);
}

versus

return (p->value == 0) && (!(p->left) != !(p->right));

Of course, both cases are pretty ugly, here.


.... without the extra parentheses:
return (p->value == 0) && (!p->left != !p->right);

explicit comparisons ...
((p->left == NULL) != (p->right == NULL));

With explicit comparisons against NULL,
as long as you have an odd number of nots, it's all the same.

((p->left == NULL) != (p->right == NULL));
((p->left != NULL) != (p->right != NULL));
((p->left != NULL) == (p->right == NULL));
 
D

Derk Gwen

# Of course one can get the effect with appropriate use of existing
# operators, but a ^^ operator would make for nice symmetry (as well as
# useful to me in something I'm working on). Am I the only one who
# would find it useful?

#define logical_equiv(p,q) (!(p)==!(q))
#define logical_xor(p,q) (!(p)!=!(q))
#define logical_implies(p,q) (!(p)<=!(q))
 
P

PlasmaDragon

Kevin D. Quitt said:
I officially nominate this question as a FAQ, and request that the first
update to the FAQ since February 7, 1999 be made.

I agree.
 
L

lawrence.jones

Kevin D. Quitt said:
Yes, for the same reason as || and &&, albeit there's no shortcutting. It
makes it *obvious* that a purely boolean expression is involved. !a ^ !b
isn't obviously purely boolean; the central operator is not boolean.

Then use the other exclusive-or operator: !a != !b.

-Larry Jones

I don't need to improve! Everyone ELSE does! -- Calvin
 
K

Keith Thompson

nrk said:
Read carefully. What I meant was that, you couldn't write:
if ( x ^ y ),
but you could write:
if ( (x != 0) ^ (y != 0) )

Yeah, that would work. (I think it's ugly, but it would work.)

If I really had a need for logical xor, I'd probably use a macro,
something like:

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

(I think that's right.)
 
C

Christopher Benson-Manica

Keith Thompson said:
#define XOR(a, b) (!(a) ^ !(b))

Finding an XOR in code would be rather annoying (to track down the
header file where it's defined), I would think.
 
A

Arthur J. O'Dwyer

For what it's worth, I've added a page to my own personal FAQ
list:
http://www.msu.edu/~pfaffben/writings/clc/logical-xor.html
Anyone have anything to add or dispute?

Nit: "Far more rarely useful"? :) How about "far less often"?

And I would appreciate a clarification about how !a != !b interacts
with doubles, and some newbie no doubt would appreciate a clarification
about how it interacts with pointers. (!NULL == (int)1, !foo == (int)0;
but I am still waiting for someone more often correct than I to address
the question of !NaN.)

-Arthur
 
B

Ben Pfaff

Arthur J. O'Dwyer said:
Nit: "Far more rarely useful"? :) How about "far less often"?

Yes, that's much better phrasing. I will update it.
And I would appreciate a clarification about how !a != !b interacts
with doubles, and some newbie no doubt would appreciate a clarification
about how it interacts with pointers. (!NULL == (int)1, !foo == (int)0;
but I am still waiting for someone more often correct than I to address
the question of !NaN.)

I'm not sure what you'd like me to say about those cases. It
seems to me that, with the possible exception of NaN, they work
out okay.
 
N

nrk

Ben said:
Yes, that's much better phrasing. I will update it.


I'm not sure what you'd like me to say about those cases. It
seems to me that, with the possible exception of NaN, they work
out okay.

I am not sure if its in the C standard, but I believe NaN is to compare
unequal to any other number and even to NaN itself. Since ! yields 0 if
the operand is not equal to 0, if the above were true, one would expect
!NaN to yield 0.

-nrk.
 
K

Keith Thompson

Ben Pfaff said:
For what it's worth, I've added a page to my own personal FAQ
list:
http://www.msu.edu/~pfaffben/writings/clc/logical-xor.html
Anyone have anything to add or dispute?

Other than the URL, there's no mention of the common abbreviation "xor";
there probably should be.

Another thing I just noticed: <iso646.h> defines the following
macros:

and &&
and_eq &=
bitand &
bitor |
compl ~
not !
not_eq !=
or ||
or_eq |=
xor ^
xor_eq ^=

The "and", "or", and "not" macros refer to the logical operators, but
the "xor" macro refers to the bitwise operator. If a logical-xor "^^"
operator were added, the asymmetry would be painful.
 
C

Christian Bau

You say that logical xor is used much more rarely than logical and/or.
Question: Has anybody _ever_ found a situation where they would have
wanted a logical xor?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top