首页 文章

C中的逻辑XOR运算符?

提问于
浏览
241

有这样的事吗?这是我第一次遇到它的实际需要,但我没有看到列出的in Stroustrup . 我打算写:

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

但是没有 ^^ 运营商 . 我可以在这里使用按位 ^ 并得到正确的答案(无论机器表示真和假)?我从不混淆 &&& ,或 ||| ,所以我对 ^^^ 犹豫不决 .

我会更自在地编写自己的 bool XOR(bool,bool) 函数 .

11 回答

  • 35

    XOR运算符不能短路;即,仅通过评估其左手操作数,您无法预测XOR表达式的结果 . 因此,没有理由提供 ^^ 版本 .

  • 16

    还有另一种方法可以做XOR:

    bool XOR(bool a, bool b)
    {
        return (a + b) % 2;
    }
    

    显然可以证明通过以下方式工作:

    #include <iostream>
    
    bool XOR(bool a, bool b)
    {
        return (a + b) % 2;
    }
    
    int main()
    {
        using namespace std;
        cout << "XOR(true, true):\t" << XOR(true, true) << endl
             << "XOR(true, false):\t" << XOR(true, false) << endl
             << "XOR(false, true):\t" << XOR(false, true) << endl
             << "XOR(false, false):\t" << XOR(false, false) << endl
             << "XOR(0, 0):\t\t" << XOR(0, 0) << endl
             << "XOR(1, 0):\t\t" << XOR(1, 0) << endl
             << "XOR(5, 0):\t\t" << XOR(5, 0) << endl
             << "XOR(20, 0):\t\t" << XOR(20, 0) << endl
             << "XOR(6, 6):\t\t" << XOR(5, 5) << endl
             << "XOR(5, 6):\t\t" << XOR(5, 6) << endl
             << "XOR(1, 1):\t\t" << XOR(1, 1) << endl;
        return 0;
    }
    
  • 4

    != 运算符用于 bool 值 .

  • 3

    以下是我认为您在C中编写XOR比较的方式:

    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);
    
  • 25

    对于真正的逻辑XOR操作,这将起作用:

    if(!A != !B) {
        // code here
    }
    

    我们否定 AB 的原因是将它们转换为布尔值 . 否定不是意图 . 将整数转换为布尔值的常见技巧是使用 !! . 这会将变量的值转换为 0 ,否则变量为 01 . 我们本可以使用 !!A != !!B 代替 . 另一种方法是使用 (_Bool)A != (_Bool)B .

  • 5

    适当的手动逻辑XOR实现取决于您希望模拟其他逻辑运算符( ||&& )与XOR的一般行为的接近程度 . 关于这些运算符有两个重要的事项:1)它们保证短路评估,2)它们引入序列点,3)它们仅评估它们的操作数一次 .

    如您所知,XOR评估不能被短路,因为结果总是取决于两个操作数 . 所以1是不可能的 . 但是2呢?如果你不关心2,那么使用标准化(即 bool )值,运算符 != 在结果方面完成XOR的工作 . 如果需要,可以使用一元 ! 轻松地对操作数进行标准化 . 因此 !A != !B 在这方面实现了正确的XOR .

    但是如果你关心额外的序列点,那么 != 和bitwise ^ 都不是实现XOR的正确方法 . 正确执行XOR(a,b)的一种可能方法可能如下所示

    a ? !b : b
    

    这实际上就像你可以制作一个自制的XOR "similar"到 ||&& . 当然,只有将XOR实现为宏时,这才有效 . 一个函数赢得了't do, since the sequencing will not apply to function'的参数 .

    有人可能会说,在每个 &&|| 都有一个序列点的唯一原因是支持短路评估,因此XOR不需要一个 . 实际上,这是有道理的 . 然而,值得考虑在中间具有序列点的XOR . 例如,以下表达式

    ++x > 1 && x < 5
    

    已经在C / C中定义了行为和特定结果(至少在排序方面) . 因此,人们可能合理地期望用户定义的逻辑XOR相同,如同

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

    而基于 != 的XOR没有此属性 .

  • 1

    (A || B) && !(A && B)

    第一部分是A OR B,即包含OR;第二部分是,不是A和B.一起得到A或B,但不是A和B.

    这将提供下面真值表中证明的XOR .

    |-----|-----|-----------|
    |  A  |  B  |  A XOR B  |
    |-----|-----|-----------|
    |  T  |  T  |   False   |
    |-----|-----|-----------|
    |  T  |  F  |   True    |
    |-----|-----|-----------|
    |  F  |  T  |   True    |
    |-----|-----|-----------|
    |  F  |  F  |   False   |
    |-----|-----|-----------|
    
  • -1
    #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(长度不同!)

  • 205

    我使用"xor"(它似乎是一个关键字;在Code::Blocks中至少它变为粗体)就像你可以使用"and"而不是 && 而"or"而不是 || .

    if (first xor second)...
    

    是的,这是有点的 . 抱歉 .

  • 461

    发布了一些好的代码,比#!=!b更好地解决了问题

    请注意,我必须添加BOOL_DETAIL_OPEN / CLOSE,以便它可以在MSVC 2010上运行

    /* From: http://groups.google.com/group/comp.std.c++/msg/2ff60fa87e8b6aeb
    
       Proposed code    left-to-right?  sequence point?  bool args?  bool result?  ICE result?  Singular 'b'?
       --------------   --------------  ---------------  ---------- ------------  -----------  -------------
       a ^ b                  no              no             no          no           yes          yes
       a != b                 no              no             no          no           yes          yes
       (!a)!=(!b)             no              no             no          no           yes          yes
       my_xor_func(a,b)       no              no             yes         yes          no           yes
       a ? !b : b             yes             yes            no          no           yes          no
       a ? !b : !!b           yes             yes            no          no           yes          no
       [* see below]          yes             yes            yes         yes          yes          no
       (( a bool_xor b ))     yes             yes            yes         yes          yes          yes
    
       [* = a ? !static_cast<bool>(b) : static_cast<bool>(b)]
    
       But what is this funny "(( a bool_xor b ))"? Well, you can create some
       macros that allow you such a strange syntax. Note that the
       double-brackets are part of the syntax and cannot be removed! The set of
       three macros (plus two internal helper macros) also provides bool_and
       and bool_or. That given, what is it good for? We have && and || already,
       why do we need such a stupid syntax? Well, && and || can't guarantee
       that the arguments are converted to bool and that you get a bool result.
         Think "operator overloads". Here's how the macros look like:
    
       Note: BOOL_DETAIL_OPEN/CLOSE added to make it work on MSVC 2010
      */
    
    #define BOOL_DETAIL_AND_HELPER(x) static_cast<bool>(x):false
    #define BOOL_DETAIL_XOR_HELPER(x) !static_cast<bool>(x):static_cast<bool>(x)
    
    #define BOOL_DETAIL_OPEN (
    #define BOOL_DETAIL_CLOSE )
    
    #define bool_and BOOL_DETAIL_CLOSE ? BOOL_DETAIL_AND_HELPER BOOL_DETAIL_OPEN
    #define bool_or BOOL_DETAIL_CLOSE ? true:static_cast<bool> BOOL_DETAIL_OPEN
    #define bool_xor BOOL_DETAIL_CLOSE ? BOOL_DETAIL_XOR_HELPER BOOL_DETAIL_OPEN
    
  • 10

    使用简单:

    return ((op1 ? 1 : 0) ^ (op2 ? 1 : 0));
    

相关问题