我可以使用按位运算符而不是逻辑运算符吗?

时间:2016-10-31 11:07:11

标签: c++ bitwise-operators logical-operators

按位运算符处理位,逻辑运算符计算布尔表达式。只要表达式返回bool,为什么我们不使用按位运算符而不是逻辑?

在这个例子中,我使用按位而不是逻辑:

#include <iostream>


int main(){

    int age;
    std::cin >> age;

    if( (age < 0) | (age > 100) ) // eg: -50: 1 | 0 = 1
        std::cout << "Invalid age!" << std::endl;

//  if( (age < 0) || (age > 100) )
//      std::cout << "Invalid age!" << std::endl;

  return 0;
}

5 个答案:

答案 0 :(得分:11)

一个可能的答案是:优化。例如:

if ((age < 0) | (age > 100))

假设age = -5,无需评估(age > 100),因为满足第一个条件(-5<0)。但是,前面的代码将评估(age > 100)表达式,这是不必要的。

使用:

if ((age < 0) || (age > 100))

将评估第一部分。

注意:在评论中提及 @Lundin 时,由于第二次分支的准确性,有时|||快选项(以及错误预测的问题)。因此,在其他表达式如此便宜的情况下,|选项 可能 更快。因此,在这些情况下了解的唯一方法是在目标平台上对代码进行基准测试。

最重要的答案是避免未定义的行为和错误:

你可以想象这段代码:

int* int_ptr = nullptr;
if ((int_ptr != nullptr) & (*int_ptr == 5))

此代码包含未定义的行为。但是,如果将&替换为&&,则不再存在未定义的行为。

答案 1 :(得分:2)

你不应该。假设您收到两个值,只有当它们都非零时才允许您继续。

b && c == true

以下条件导致以下情况:b & c == 0,而if (b && c) { // This block will be entered } if (b & c) { // This block won't }

"\n"

答案 2 :(得分:1)

即使您使用逐位运算符获得相同的结果,由于性能原因,最好在此处使用逻辑运算符。

在表达式(age < 0) || (age > 100)中,仅当(age > 100)(age < 0)时,才会计算第二个条件false。对于这样的表达式,编译器生成如下代码:

cmpl   $0x0,-0x4(%rbp)                 
js     1004010f9 <main+0x19>  // <-- Skip right expr evaluation if left true
cmpl   $0x64,-0x4(%rbp)               
jle    100401100 <main+0x20>

||不会产生任何额外的分支,以便能够跳过第二次表达式评估。

答案 3 :(得分:1)

|||之间存在明显差异。

与该语言中的大多数其他运算符不同,逻辑||运算符明确指定了评估顺序。必须在第二个之前评估||的第一个操作数。第二个根本不需要评估。

这与作为大多数运算符的|根本不同:评估顺序未指定,并且将评估两个表达式。即使在发现一个操作数非零的情况下,仍然会评估另一个操作数的副作用。

意味着像f1() || f2()这样的代码将始终评估为此伪代码:

if(f1() != 0)
{
  f2();
}

f1() | f2()将以程序员无法知道的未指定顺序执行这两个函数。

这也意味着像“||这样的语句比|”更快是天真的。当然,在||的情况下,第二个操作数不一定被评估,但这是以分支为代价的,以及对如何允许编译器重新排序表达式的限制。通常更快的哪个运营商并不明显。

答案 4 :(得分:0)

答案是肯定的,你可以。问题是你为什么要这样做?我可以列举一些你不应该提出的理由:

  1. 对其他程序员来说可能会非常混乱。
  2. 很容易错过其中一个操作数不是bool类型,这会导致细微的错误。
  3. 操作数评估的顺序未定义。
  4. 它弄乱了短路规则。
  5. 说明最后一点:

    bool f1() {
        cout << "f1" << endl;
        return true;
    }
    
    bool f2() {
        cout << "f2" << endl;
        return true;
    }
    
    int main() {
        if (f1() || f2()) {
            cout << "That was for ||" << endl;
        }
        if (f1() | f2()) {
            cout << "That was for |" << endl;
        }
        return 0;
    }
    

    打印:

    f1
    That was for ||
    f1
    f2
    That was for |
    

    假设f2可能有明显的副作用(if (okToDestroyWorld && destroyWorld()) ...),差异可能很大。它不会让Java程序员感到惊讶(其中|||实际上通过语言规范为布尔定义了),但这在C ++中并不常见。

    我可以想到使用按位运算符进行布尔运算的一个原因:如果需要XOR。没有^^运算符,只要if (a ^ b)abbool就可以了,并且不会产生任何副作用。

相关问题