代码之家  ›  专栏  ›  技术社区  ›  Jay Conrod

在C++中使用位运算算子实现Booleans

  •  62
  • Jay Conrod  · 技术社区  · 18 年前

    我有时会遇到这样的情况,即我希望两个条件中的一个为真(XOR),所以我只是将^运算符放入一个条件表达式中。有时我还希望对条件的所有部分进行评估,以确定结果是否正确(而不是短路),因此我使用&和|。有时我还需要累积布尔值,并且&=和|=可能非常有用。

    9 回复  |  直到 14 年前
        1
  •  62
  •   Cheers and hth. - Alf    10 年前

    || 和 && true 或 false . 没有别的了。

    | & 和 ^ 是按位运算符。当您操作的数字域仅为1和0时,它们完全相同,但如果您的布尔值不是严格意义上的1和0,就像C语言的情况一样,您可能最终会出现一些您不想要的行为。例如:

    BOOL two = 2;
    BOOL one = 1;
    BOOL and = two & one;   //and = 0
    BOOL cand = two && one; //cand = 1
    

    但是,在C++中, bool 类型保证仅为 符合事实的 1 0 b = b && x 就这样吧。

        2
  •  33
  •   polarbear    17 年前

    首先,如果您使用的值不是 false true (或 0 1 ^

    int one = 1;
    int two = 2;
    
    // bitwise xor
    if (one ^ two)
    {
      // executes because expression = 3 and any non-zero integer evaluates to true
    }
    
    // logical xor; more correctly would be coded as
    //   if (bool(one) != bool(two))
    // but spelled out to be explicit in the context of the problem
    if ((one && !two) || (!one && two))
    {
      // does not execute b/c expression = ((true && false) || (false && true))
      // which evaluates to false
    }
    

    第二 | , & 和 ^

    bool result = true;
    result = result && a() && b();
    // will not call a() if result false, will not call b() if result or a() false
    

    不会始终给出与相同的结果(或结束状态)

    bool result = true;
    result &= (a() & b());
    // a() and b() both will be called, but not necessarily in that order in an
    // optimizing compiler
    

    a() b() ,或者其他人可能会在不了解依赖关系的情况下出现并更改它们,并导致一个讨厌的(通常是仅发布版本)bug。

        3
  •  13
  •   Mark Borgerding    18 年前

    a != b
    

        4
  •  11
  •   kokos    18 年前


    我想你也用叉子吃苹果吧?它是有效的,但它让人惊讶,所以最好不要这样做。

        5
  •  10
  •   Cheers and hth. - Alf    12 年前

    位级运算符的缺点。

    你问:

    “是否有任何理由不使用按位运算符 & , | ^

    是的 ! && 和 ||

    • 论元转换 bool 0 和 1

    • 放心 短路评估
      这可以解释为树值逻辑,具有 , 错误的 和 .

    • 可读文本等价物 not and or
      作为注释中的读者锑注释,位级运算符也有替代标记,即 bitand bitor xor 和 compl ,但在我看来,这些都不如 和 , 不 .

    简单地说,高级运算符的每一个这样的优点都是位运算符的缺点。

    1 & 2 → 0 虽然 1 && 2 true . 而且 ^


    如何表达逻辑 在C++中。

    a && b ^ c
    

    你可能会得到意想不到的结果 a && (b ^ c)

    (a && b) != c
    

    a ^ b ^ c a b c 而是说,“一个奇数的 A. , B C “是真的”,可能是其中一个或全部3个…

    表示一般情况,或 , 和 ,就写吧

    (a + b + c) == 1
    

    或者,与非- 布尔 布尔 :

    (!!a + !!b + !!c) == 1
    


    使用 &=

    你进一步阐述,,

    “有时,我还需要累积布尔值 & |=?

    任何 条件满足,并且 告诉你如何从一个到另一个。也就是说,你只需要其中一个。原则上你可以使用 *= &&=

    struct Bool
    {
        bool    value;
    
        void operator&=( bool const v ) { value = value && v; }
        operator bool() const { return value; }
    };
    
    #include <iostream>
    
    int main()
    {
        using namespace std;
    
        Bool a  = {true};
        a &= true || false;
        a &= 1234;
        cout << boolalpha << a << endl;
    
        bool b = {true};
        b &= true || false;
        b &= 1234;
        cout << boolalpha << b << endl;
    }
    

    true
    false
    

    结果差异的原因是位级别 &= 不提供到的转换 布尔 它的右手边的论点。

    &

    符合事实的 ,然后最好定义一个运算符(例如,如上所述)或命名函数,或者使用右侧表达式的显式转换,或者完整地编写更新。

        6
  •  3
  •   bk1e    18 年前

    与帕特里克的回答相反,C++没有 ^^ 执行短路异或的操作员。如果你想一想 ^^ 运算符无论如何都没有意义:对于异或,结果始终取决于两个操作数。然而,帕特里克对非暴力行为的警告- bool “布尔”类型在比较时同样适用 1 & 2 到 1 && 2 GetMessage() 函数,它返回一个三态 BOOL :非零, 0 -1

    使用 & && | 而不是 || 这不是一个罕见的打字错误,所以如果你是故意这样做的,它值得一个评论,说明原因。

        7
  •  2
  •   genix    18 年前

    bool onlyAIsTrue = (a && !b); // you could use bitwise XOR here
    bool onlyBIsTrue = (b && !a); // and not need this second line
    if (onlyAIsTrue || onlyBIsTrue)
    {
     .. stuff ..
    }
    

    您可能认为使用布尔值似乎没有必要,但它有两个主要方面的帮助:

    EDIT:您没有明确表示希望使用“if”语句的条件(尽管这似乎最有可能),这是我的假设。但我关于中间布尔值的建议仍然有效。

        8
  •  1
  •   Anoop Menon    8 年前

        9
  •  0
  •   spoulson    18 年前

    IIRC,当尝试将位操作的结果作为BOOL来进行转换时,许多C++编译器将发出警告。您必须使用类型转换才能使编译器满意。

    在if表达式中使用按位操作也会受到同样的批评,尽管编译器可能不会这样做。任何非零值都被认为是真的,因此类似“if(7&3)”的内容将是真的。这种行为在Perl中是可以接受的,但C/C++是非常显式的语言。我认为斯波克眉毛是尽职调查我会加上“==0”或“!=0”来明确你的目标是什么。

    但无论如何,这听起来像是个人喜好。我会通过lint或类似工具运行代码,看看它是否也认为这是一种不明智的策略。就个人而言,它读起来像是一个编码错误。