&
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
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.
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.
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 bool
s 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.
I can't say what was in the heads of Kernighan and Ritchie 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.
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.
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.
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 ...
来源:https://stackoverflow.com/questions/837265/why-is-there-no-operator-in-c-c