有这样的东西吗?这是我第一次遇到对它的实际需求,但我在Stroustrup中没有看到它的列表。我打算写:

// Detect when exactly one of A,B is equal to five.
return (A==5) ^^ (B==5);

但是没有^^操作符。我可以使用这里的位^并得到正确的答案(不管机器表示的是真还是假)吗?我从不把&和&&混在一起,或者|和||混在一起,所以我不太愿意把^和^^混在一起。

我更愿意写我自己的bool XOR(bool,bool)函数。


当前回答

正确的手动逻辑异或实现取决于您希望用异或模拟其他逻辑运算符(||和&&)的一般行为的程度。关于这些操作符有两个重要的事情:1)它们保证短路计算,2)它们引入序列点,3)它们只计算操作数一次。

正如您所理解的,异或求值不能被短路,因为结果总是取决于两个操作数。所以1是不可能的。那么2呢?如果你不关心2,那么对于规范化的(即bool)值,operator !=在结果方面完成XOR的工作。如果需要,操作数可以很容易地用unary !规范化。因此,A != !B在这方面实现了适当的异或。

但是如果你关心额外的序列点,无论是!=还是位^都不是实现异或的正确方法。正确执行异或(a, b)的一种可能方法如下所示

a ? !b : b

这实际上是你能得到的最接近于制作一个自制的异或“类似”||和&&。当然,这只有在将XOR作为宏实现时才会起作用。函数不会这样做,因为排序将不适用于函数的参数。

有人可能会说,在每个&&和||处都有序列点的唯一原因是为了支持短路求值,因此XOR不需要。实际上,这是有道理的。然而,考虑一个中间有序列点的异或是值得的。例如,下面的表达式

++x > 1 && x < 5

已经在C/ c++中定义了行为和特定的结果(至少在排序方面)。因此,用户定义的逻辑XOR可能也有相同的期望,如

XOR(++x > 1, x < 5)

而基于!=的异或没有此属性。

其他回答

以下是我认为在c++中如何编写异或比较的方法:

bool a = true;   // Test by changing to true or false
bool b = false;  // Test by changing to true or false
if (a == !b)     // THIS IS YOUR XOR comparison
{
    // do whatever
}

证明

XOR TABLE
 a   b  XOR
--- --- ---
 T   T   F
 T   F   T
 F   T   T
 F   F   F

a == !b TABLE
 a   b  !b  a == !b
--- --- --- -------
 T   T   F     F
 T   F   T     T
 F   T   F     T
 F   F   T     F

证明是,对输入和输出的详尽研究表明,在两个表中,对于每个输入集,两个表中的结果总是相同的。

因此,最初的问题是如何写:

return (A==5) ^^ (B==5)

答案是

return (A==5) == !(B==5);

如果你喜欢,也可以写下来

return !(A==5) == (B==5);
#if defined(__OBJC__)
    #define __bool BOOL
    #include <stdbool.h>
    #define __bool bool
#endif

static inline __bool xor(__bool a, __bool b)
{
    return (!a && b) || (a && !b);
}

它按定义工作。条件是用来检测你是否在使用Objective-C,它要求BOOL而不是BOOL(长度不同!)

异或运算符不能短路;也就是说,你不能仅仅通过计算一个XOR表达式的左操作数来预测它的结果。因此,没有理由提供^^版本。

正确的手动逻辑异或实现取决于您希望用异或模拟其他逻辑运算符(||和&&)的一般行为的程度。关于这些操作符有两个重要的事情:1)它们保证短路计算,2)它们引入序列点,3)它们只计算操作数一次。

正如您所理解的,异或求值不能被短路,因为结果总是取决于两个操作数。所以1是不可能的。那么2呢?如果你不关心2,那么对于规范化的(即bool)值,operator !=在结果方面完成XOR的工作。如果需要,操作数可以很容易地用unary !规范化。因此,A != !B在这方面实现了适当的异或。

但是如果你关心额外的序列点,无论是!=还是位^都不是实现异或的正确方法。正确执行异或(a, b)的一种可能方法如下所示

a ? !b : b

这实际上是你能得到的最接近于制作一个自制的异或“类似”||和&&。当然,这只有在将XOR作为宏实现时才会起作用。函数不会这样做,因为排序将不适用于函数的参数。

有人可能会说,在每个&&和||处都有序列点的唯一原因是为了支持短路求值,因此XOR不需要。实际上,这是有道理的。然而,考虑一个中间有序列点的异或是值得的。例如,下面的表达式

++x > 1 && x < 5

已经在C/ c++中定义了行为和特定的结果(至少在排序方面)。因此,用户定义的逻辑XOR可能也有相同的期望,如

XOR(++x > 1, x < 5)

而基于!=的异或没有此属性。

(a || b) && !(a && b)

第一部分是A或B,即包含或;第二部分是,不是A和B,合在一起你得到A或B,但不是A和B都有。

这将提供在下面的真值表中证明的异或。

|-----|-----|-----------|
|  A  |  B  |  A XOR B  |
|-----|-----|-----------|
|  T  |  T  |   False   |
|-----|-----|-----------|
|  T  |  F  |   True    |
|-----|-----|-----------|
|  F  |  T  |   True    |
|-----|-----|-----------|
|  F  |  F  |   False   |
|-----|-----|-----------|