16

&&&|||。为什么^没有^^

我知道它不会短路,但它会有不同的语义。在 C 中,true实际上是任何非零值。按位异或并不总是与逻辑异或相同:

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)

既然你不能总是依赖一个真正的价值是1or -1,那么^^运算符不是很有帮助吗?我经常不得不做这样奇怪的事情:

if(!!a ^ !!b) // looks strange
4

7 回答 7

54

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.

于 2009-05-07T22:44:09.550 回答
24

从技术上讲,一个已经存在:

a != b

因为如果操作数的真值不同,这将评估为真。

编辑:

沃尔特的评论:

(!a) != (!b)

是正确的,因为我上面的答案不适用于int类型。如果他添加他的答案,我将删除我的。

再次编辑:

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.

于 2009-05-07T22:04:23.623 回答
5

对于非bool操作数,我想你想要的是a ^^ b被评估为:

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

好吧,您有上述选项,并且您在其他答案中列出了一些选项。

运算符^^对于操作数来说是多余的bool。仅谈论布尔操作数,为了争论,让我们假设它^是按位的并且^^以逻辑 XOR 的形式存在。然后,您有以下选择:

  • & - 按位与 -- 总是计算两个操作数
  • &&- 逻辑与 - 并不总是评估两个操作数
  • | - 按位或 - 总是计算两个操作数
  • ||- 逻辑或 - 并不总是评估两个操作数
  • ^ - 按位异或 - 必须始终评估两个操作数
  • ^^- 逻辑异或 - 必须始终评估两个操作数

他们为什么不创建^^本质上将数值转换为bools 然后充当 s ^?这是个好问题。也许是因为它比&&and更容易混淆,也许是因为你可以很容易地用其他运算符||构造等价的运算符。^^

于 2009-05-07T22:04:01.813 回答
5

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.

于 2009-05-07T22:28:59.210 回答
1

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.

于 2009-05-08T05:59:30.500 回答
1

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.

于 2009-05-08T07:40:05.330 回答
0

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 ...

于 2009-05-08T07:51:50.263 回答