views:

738

answers:

7

& has &&. | has ||. Why doesn't ^ have ^^?

I understand that it wouldn't be short-circuiting, but it would have different semantics. In C, true is really any non-zero value. Bitwise XOR is not always the same thing as logical XOR:

int a=strcmp(str1,str2);// evaluates to 1, which is "true"
int b=strcmp(str1,str3);// evaluates to 2, which is also "true"
int c=a ^^ b; // this would be false, since true ^ true = false
int d=a ^ b; //oops, this is true again, it is 3 (^ is bitwise)

Since you can't always rely on a true value being 1 or -1, wouldn't a ^^ operator be very helpful? I often have to do strange things like this:

if(!!a ^ !!b) // looks strange
+2  A: 

For non-bool operands, I guess what you would want is for a ^^ b to be evaluated as:

(a != 0) ^ (b != 0)

Well, you have the above option and you have a few options listed in other answers.

The operator ^^ would be redundant for bool operands. Talking only about boolean operands, for the sake of argument, let's pretend that ^ was bitwise-only and that ^^ existed as a logical XOR. You then have these choices:

  • & - Bitwise AND -- always evaluates both operands
  • && - Logical AND -- does not always evaluate both operands
  • | - Bitwise OR -- always evaluates both operands
  • || - Logical OR -- does not always evaluate both operands
  • ^ - Bitwise XOR -- must always evaluate both operands
  • ^^ - Logical XOR -- must always evaluate both operands

Why didn't they create ^^ to essentially convert numerical values into bools and then act as ^? That's a good question. Perhaps because it's more potentially confusing than && and ||, perhaps because you can easily construct the equivalent of ^^ with other operators.

Eddie
His point is that if you were to do the operation (1 ^^ 2) it would evaluate to false when he believes it should evaluate to true as would (1 ^^ 2). I'm not saying I agree, I'm just pointing out that it's not actually redundant.
Joseph
Good point. I've updated my answer.
Eddie
+20  A: 

Technically, one already exists:

a != b

since this will evaluate to true if the truth value of the operands differ.

Edit:

Volte's comment:

(!a) != (!b)

is correct because my answer above does not work for int types. I will delete mine if he adds his answer.

Edit again:

Maybe I'm forgetting something from C++, but the more I think about this, the more I wonder why you would ever write if (1 ^ 2) in the first place. The purpose for ^ is to exclusive-or two numbers together (which evaluates to another number), not convert them to boolean values and compare their truth values.

This seems like it would be an odd assumption for a language designer to make.

John Rasch
For non-boolean inputs, you'll want to use `((!!a) != (!!b))` (with extra parentheses for paranoia!).
kquinn
of course, this only works on boolean types, so you'll need a cast to use it with ints as in the OP's example. +1 anyways.
rmeador
'(!a) != (!b)' will have the same effect.
Volte
I actually read this question incorrectly, I saw the comments in his code (which say true and false) but missed the int type - I'll have to trust you guys with the casting though my C++ is a little rusty
John Rasch
No, 1 != 2 is true, when 1 ^^ 2 would be false. You end up having to wrap it in !s, in which case, I think !!1 ^ !!2 would much more clear.
Zifre
@Volte: You should *answer* with your version, since it's more accurate than the above answer.
Eddie
@John Rasch: In response to your last edit, think about strcmp, which returns an integer. It does not return -1,0,1, but it returns <0, 0, >0. Thus, if you wanted "if (strcmp(a,b) ^^ strcmp(a,c))" then the OP's question is reasonable.
Eddie
+3  A: 

I can't say what was in the heads of Kernighan and Richie when they invented C, but you made a brief reference to "wouldn't be short-circuiting", and I'm guessing that's the reason: It's not possible to implement it consistently. You can't short-circuit XOR like you can AND and OR, so ^^ could not fully parallel && and ||. So the authors might well have decided that making an operation that sort of kind of looks like its parallel to the others but isn't quite would be worse than not having it at all.

Personally, the main reason I use && and || is for the short-circuit rather than the non-bitwise. Actually I very rarely use the bitwise operators at all.

Jay
+38  A: 

Dennis Ritchie answers

There are both historical and practical reasons why there is no ^^ operator.

The practical is: there's not much use for the operator. The main point of && and || is to take advantage of their short-circuit evaluation not only for efficiency reasons, but more often for expressiveness and correctness.
[...]
By contrast, an ^^ operator would always force evaluation of both arms of the expression, so there's no efficiency gain. Furthermore, situations in which ^^ is really called for are pretty rare, though examples can be created. These situations get rarer and stranger as you stack up the operator--

if (cond1() ^^ cond2() ^^ cond3() ^^ ...) ...

does the consequent exactly when an odd number of the condx()s are true. By contrast, the && and || analogs remain fairly plausible and useful.

Don
Wow, I wasn't expecting Dennis Rithchie to answer my question :). See Terry Donaghe's comment. He actually does give some very good points. +1
Zifre
+1 for Dennis Ritchie!
Anthony Cuozzo
+1  A: 

Another workaround to the ones posted above (even if it requires another branch in the code) would be:

if ( (a? !b : b ) )

that is equivalent to xor.

David Rodríguez - dribeas
Yes, of course they're are workarounds, but I think a real ^^ operator would be more clear about your intentions. Your example is not that obvious.
Zifre
+1  A: 

In Java the ^ operator indeed does do logical XOR when used on two boolean operands (just like & and | in Java do non-short-circuiting logical AND and OR, respectively, when applied to booleans). The main difference with C / C++ is that C / C++ allows you to mix integers and booleans, whereas Java doesn't.

But I think it's bad practice to use integers as booleans anyway. If you want to do logical operations, you should stick to either bool values, or integers that are either 0 or 1. Then ^ works fine as logical XOR.

An analogous question would be to ask, how would you do non-short-circuiting logical AND and OR in C / C++? The usual answer is to use the & and | operators respectively. But again, this depends on the values being bool or either 0 or 1. If you allow any integer values, then this does not work either.

newacct
A: 

Regardless of the case for or against ^^ as an operator, you example with strcmp() sucks. It does not return a truth value (true or false), it returns a relation between its inputs, encoded as an integer.

Sure, any integer can be interpreted as a truth value in C, in which case 0 is "false" and all other values are "true", but that is the opposite of what strcmp() returns.

Your example should begin:

int a = strcmp(str1, str2) == 0; // evaluates to 0, which is "false"
int b = strcmp(str1, str3) == 0; // evaluates to 0, which is also "false"

You must compare the return value with 0 to convert it to a proper boolean value indicating if the strings were equal or not.

With "proper" booleans, represented canonically as 0 or 1, the bitwise ^ operator works a lot better, too ...

unwind