【问题标题】:What's the point of logical operators vs. bitwise operators逻辑运算符与位运算符的意义何在
【发布时间】:2015-11-24 20:31:10
【问题描述】:

鉴于此语句是一个逻辑运算

 ((a > 5) && (b > 4))

而且这个语句是按位运算

   ((a > 5) & (b > 4)) 

以上两种说法不等价。

因为(a > 5){0,1}的一个元素

那么,为什么我们需要logical operators & bitwise-operation

编辑:感谢所有反馈。关于逻辑运算符的短路行为,我实际上不希望这种行为 - 我正在为 GPU 编写代码,其中分支会降低性能:短路会导致两个分支而不是代码中的一个。

对于 C 中的数值比较,在不需要短路的情况下,逻辑和按位似乎具有相同的行为。就我而言,按位运算比逻辑运算要快。

对于没有将这些细节放在原始帖子中,我深表歉意。

【问题讨论】:

标签: c++ c bitwise-operators


【解决方案1】:

我认为不,举这个例子(0b - 表示二进制):

a = 0b00000010
b = 0b00000100

现在,ab 都不是 0。但是 a & b == 0(由于按位与的定义方式)。

但是a && b != 0(因为如果至少一个操作数为 0,则逻辑与结果为 0 - 上面的 ab 不是这种情况)。


还有短路求值,如果&& 中的左操作数为0,则不会对右操作数进行求值,因为结果肯定为0(例如,正如已经提到的0 && x == 0,无论x 的值如何)。

【讨论】:

    【解决方案2】:
    • 逻辑运算符在组合它们之前将它们的操作数转换为bool,并且逻辑运算符的结果始终也是bool。位运算符不这样做(但是,对于 bool 的操作数,这在两种运算符之间没有区别)。
    • 逻辑运算符可用于许多可转换为 bool 的操作数类型,而位运算符在特定情况下仅适用于少数类型,并且位运算符的输出是有类型的(并不总是 bool)。
    • 逻辑运算符是快捷方式。例如在&& 的情况下,这意味着:如果第一个操作数为假,则甚至不计算第二个操作数,因为无论第二个操作数的值如何,整个表达式(假 && 某些东西)已经为假。李>

    逻辑快捷操作符通常在以下情况下被利用:

    // If mypointer is NULL, then mypointer->is_whatever()
    // isn't evaluated so it doesn't cause a NULL pointer crash.
    if (mypointer && mypointer->is_whatever()) {
        // do my thing
    }
    

    【讨论】:

    • Logical operators 在 C 中产生 int (我认为是遗留原因)。如果这在 C++ 中有所不同,请向 OP 抱怨两种不同的语言。
    • @Olaf 你说得对,旧版 C 没有 bool 类型,但幸运的是它对我的回答影响不大。即使bool 表达式的类型是int,它的可能值通常也只有0 或1。这仍然是一个好点。
    • 我不谈论遗留 C,而是 C11,正如链接的标准(最终草案)应该表明的那样。当我在引入 bool/_Bool 的 C99 标准中阅读此内容时,我自己感到很失望
    • 我明白了,bool 即使在较新的版本中也会扩展为整数。我已经很久没有编写纯 C 语言了,但这对我来说也很失望。如果我们谈论强制转换(如(bool)(expression)),这确实是一个区别,但幸运的是,无论类型如何,逻辑运算符仍然按预期处理操作数和输出(操作数和结果被视为bool)。
    • 我主要是评论,因为问题被标记为两种语言。人们如此不知道他们已经漂流了很长一段时间(直到 C99)并且仍然没有被并行开发(我认为他们永远不会这样做)。
    【解决方案3】:

    逻辑运算符用于比较多个值的真实性。

    例如,您使用&& 运算符来查看两个值是否都是true


    位运算符用于隔离和修改值中的位。

    例如,要关闭 8 位值中除 1 之外的所有位,您可以这样做:

    val & 00100000
    

    在上面的例子中,第 6 位(从 1 开始)或第 5 位(从 0 开始)保持不变,其他位关闭。


    这两种运算符的相似之处在于它们都产生 0 或 1。

    例如,拿这些:

    1 || 0
    

    以上将产生1,因为其中一个值等于1。但是,如果我们将运算符切换为&&,它将产生 0。

    在您尝试的所有运算符中,他们都会给出10truefalse。那是因为没有中间:不存在评估为“某种意义上的真”或“可能是假的”的表达式。

    而且我认为按位运算符总是“产生” 1 或 0 的原因是不言自明的:bit-wise;位是 1 或 0。

    【讨论】:

    • 它没有解释比较的差异。请注意,比较结果为整数 01,仅此而已。
    • @Olaf 它没有解释差异吗?我认为查看每个部分的第一行可以解释差异。你建议我讨论什么?
    • a > 5 产生01b > 4 同样。应用 bitops 产生 01,与 logops 相同。因此,对于这个问题,结果将是相同的(至少对于 C,它返回一个 int 进行比较等)。然而,行为却存在显着差异。
    • @Olaf 我更新了我的答案。告诉我你的想法;我可能误解了你的评论。
    • 请仔细阅读我的最后一句话非常。如果您使用 C 编程,您可能已经利用了差异(我总是想知道为什么经常忘记这一点)。请注意,此属性不仅是 C,而且大多数其他语言都有它。包括 Python。 IIRC,Ada 有两种 logops 变体(有点不确定它是一种不同的语言)。
    【解决方案4】:

    并非所有用作布尔值的表达式都计算为 0 或 1;虽然 0 被视为假,但 0 以外的任何东西都被视为真。因此,例如,1 && 2 为真,但1 & 2 不为真,即使 1 和 2 都被视为真。

    另外,正如其他人指出的那样,如果第一个表达式足以确定整体值(“短路”),逻辑运算符将不会计算第二个表达式,这显然不能用按位版本完成(嗯,不那么频繁;0 & ? 不管 ? 是什么都将为 0,因此 ? 不需要评估以获得最终值,但 & 不能那样工作)。

    【讨论】:

    • 你忘记了最重要的区别,这使得 logop 很难被 bitops 取代。
    • @Olaf:感谢(我认为)投反对票以及没有解释“最重要的区别”是什么。我什至不能说你是错的(尽管我认为你是对的),因为你还没有确定你在说什么,这限制了我和其他人可以从你的评论中拿走的东西。
    • 你应该小心你的假设。但是,我支持我所做的事情,并且一旦更正,我很乐意删除 DV(无论如何这是我的想法。重点是每个程序员都应该知道这一点,因为大多数命令式编程语言都支持它。我会给你以下提示: (p != NULL) & (p->value == 1) 有什么问题(假设类型正确)当然,请关注&。(你可能会说我讨厌,但我真的认为这非常重要)。如果您编辑了答案,请发表评论,我保证在添加 DV 后将其删除。
    • @Olaf:对 DV 不太关心,但很高兴见到你,这是非常重要的一点,你觉得有必要把它变成猜谜游戏。
    • 您不同意这是最重要的区别吗?没有这个,像上面这样的表达式将是不可能的,并且更难以实现,对于循环条件更是如此。对于“游戏”:我很确定你从现在开始会记住这一点。也许与有关,但你会:-)没关系! (按照承诺,我删除了 DV)
    猜你喜欢
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 2014-07-07
    • 1970-01-01
    相关资源
    最近更新 更多