【问题标题】:What is the difference between bitwise and logical operators inside conditional statements in C?C中条件语句中的位运算符和逻辑运算符有什么区别?
【发布时间】:2015-06-30 21:21:54
【问题描述】:

网上有很多问题是指按位运算符和逻辑运算符之间的区别。希望我已经做了一个很好的搜索,它们都没有专门研究在条件语句中使用它们是否相同,也没有专门参考 C 语言。大多数人提到 C++ 和 C#,我不知道相同的答案是否也适用于 C 语言。

这是我编写的用于测试发生了什么的示例代码:

// Difference between logical && and bitwise & //

#include <stdio.h>

#define TRUE 123>45
#define FALSE 4>2342

void print_tt(int table[][4]);

int main(void) {

    int and_tt[2][4];   // AND truth table
    int or_tt[2][4];    // OR truth table

    // Create truth table for logical and bitwise AND operator all in one 2d array
    and_tt[0][0] = TRUE && TRUE ? 1 : 0;
    and_tt[0][1] = TRUE && FALSE ? 1 : 0;
    and_tt[0][2] = FALSE && TRUE ? 1 : 0;
    and_tt[0][3] = FALSE && FALSE ? 1 : 0;
    and_tt[1][0] = TRUE & TRUE ? 1 : 0;
    and_tt[1][1] = TRUE & FALSE ? 1 : 0;
    and_tt[1][2] = FALSE & TRUE ? 1 : 0;
    and_tt[1][3] = FALSE & FALSE ? 1 : 0;

    // Create truth table for logical and bitwise OR operator all in one 2d array
    or_tt[0][0] = TRUE || TRUE ? 1 : 0;
    or_tt[0][1] = TRUE || FALSE ? 1 : 0;
    or_tt[0][2] = FALSE || TRUE ? 1 : 0;
    or_tt[0][3] = FALSE || FALSE ? 1 : 0;
    or_tt[1][0] = TRUE | TRUE ? 1 : 0;
    or_tt[1][1] = TRUE | FALSE ? 1 : 0;
    or_tt[1][2] = FALSE | TRUE ? 1 : 0;
    or_tt[1][3] = FALSE | FALSE ? 1 : 0;

    puts("_______AND_______");
    puts("Logical   Bitwise");
    print_tt(and_tt);

    puts("_______OR________");
    puts("Logical   Bitwise");
    print_tt(or_tt);

}


// prints the truth table of the bitwise and logical operator given side by side
void print_tt(int table[][4]) {
    int i;
    for(i=0; i<4 ; ++i) {
        printf("%-10s%s\n", table[0][i] ? "true" : "false",
            table[1][i] ? "true" : "false");
    }
}

程序的输出是:

_______AND_______
Logical   Bitwise
true      true
false     false
false     false
false     false
_______OR________
Logical   Bitwise
true      true
true      true
true      true
false     false

这证明了位运算符和逻辑运算符之间没有区别。修改TRUEFALSE宏的定义,把剩下的比较运算符也包括进去,可以看出又没有区别了。

因此,如果存在差异,则可能与编译器解释语句的方式或代码的效率有关。

总之,在特定情况下,当我们在条件语句中的两个或多个比较操作的结果之间有一个按位或逻辑运算符时,我们应该使用两者中的哪一个,主要是为了提高效率?

【问题讨论】:

  • 你的证明中有一个逻辑错误 :-) 你已经证明在一组案例中没有区别,并且错误地推断出所有案例都是正确的。

标签: c conditional-statements bitwise-operators logical-operators


【解决方案1】:

您只检查值01。尝试其他值,您会发现差异。

int a = 4, b = 2;

puts(a && b ? "true" : "false");
puts(a & b  ? "true" : "false");

打印出来:

true
false

位运算符仅适用于整数。逻辑运算符可用于指针、浮点数和其他非整数类型。

还有短路。如果第一个操作数足够,逻辑运算符将不会计算第二个操作数。

int a() { puts("a"); return 0; }
int b() { puts("b"); return 1; }

int main() {
    puts(a() && b() ? "true" : "false");
    puts("---");
    puts(a() & b()  ? "true" : "false");
}

打印出来:

a
false
---
a
b
false

注意使用&amp; 时如何打印b。没有短路,所以&amp; 调用这两个函数,而&amp;&amp; 只调用a()

更微妙的是,与&amp;&amp; 不同,&amp; 不会对其操作数施加求值顺序。输出同样可以将 ab 打印输出颠倒过来。

a
false
---
b
a
false

如果您将所有这些差异放在一边,那么是的,运算符是等价的。在这种情况下,不用担心效率。使用语义正确的运算符:逻辑运算符。

(如果它可以帮助您放松心情,那么效率不会有任何差异。编译器非常聪明,并且肯定会发出最佳字节码来评估这些表达式,无论您使用哪个运算符。)

【讨论】:

  • 也短路了。
  • 我知道这种差异,但我的问题没有明确提到的是,当我们在条件语句中的两个或多个比较操作的结果之间有一个按位或逻辑运算符时.
  • 我还看到您发布的所有这些信息分散在许多不同的网站上,但它们都提到了 C++ 或 C#。现在我也知道 C 语言也是如此,所有内容都集中在一个地方。
【解决方案2】:
1101 & 0010 = 0000, 1101 && 0010 = True
1101 | 0010 = 1111, 1101 || 0010 = True

原因是按位分别比较每个位,而逻辑将整个位串视为一位真或假。在查看一位的位串时,逻辑运算符和位运算符之间确实没有区别。另一种思考方式是按位运算符是从整数到整数的函数,而逻辑运算符是从布尔值到布尔值的函数。

通过调用table[0][i] ? "true" : "false",您将整数转换为位。如果将其保留为整数,您将看到两种运算符之间的区别。

【讨论】:

  • 你的意思是,123>45 的输出是一个 0x1 的一位字符串?
  • 不,它取决于实现。但是当您打印时,您将转换为字符串 true 或 false。如果您只是将值打印为整数而不是转换为布尔值,您会看到差异。
【解决方案3】:

&amp;&amp; 是布尔运算符,而&amp; 是位运算符。

&amp; 是对两个整数的 and 运算。示例:1100 &amp; 1001 = 1101,所以12 &amp; 9 = 13

&amp;&amp; 只检查(左和右)值是否都为 TRUE(即非零)。

1 &amp; 2 例如是0,因为 1 和 2 的二进制和是 0。例如:01 &amp; 10 = 00

虽然1 &amp;&amp; 2 类似于TRUE &amp;&amp; TRUE,但它也等于true。所以对于&amp;&amp;,左值和右值都先“转换”为布尔表达式,然后进行比较。

另外,不要忘记编译器能够短路&amp;&amp; 表达式。喜欢这个:

bool variable = isValid && compareSomething()

不评估正确的值,因为它不需要。第一个已经明确指出variableisValid,只要isValid 为真。

Read more

【讨论】:

    猜你喜欢
    • 2015-07-03
    • 2021-01-02
    • 2012-12-16
    • 2020-04-07
    • 2014-01-17
    • 2015-11-28
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    相关资源
    最近更新 更多