C中条件语句内的位运算符和逻辑运算符之间有什么区别?

时间:2015-04-22 23:27:06

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

网上有很多问题涉及按位运算符和逻辑运算符之间的差异。希望我做了一个很好的搜索,当在条件语句中使用时,他们都没有专注于它们是否相同,也没有专门用于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宏的定义以包含剩余的比较运算符,可以看出再没有差异。

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

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

3 个答案:

答案 0 :(得分:7)

您只需检查值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

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

在更微妙的说明中,与&&不同,&不对其操作数强加评估顺序。输出同样可以使ab打印输出相反。

a
false
---
b
a
false

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

(如果它有助于缓解你的想法,那么效率就没有区别。编译器非常聪明,无论你使用哪种算法,编译器都会发出最佳字节码来评估这些表达式。)

答案 1 :(得分:1)

1101 & 0010 = 0000, 1101 && 0010 = True
1101 | 0010 = 1111, 1101 || 0010 = True

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

通过调用table[0][i] ? "true" : "false",您将整数转换为一个位。如果将它保留为整数,您将看到两种类型的运算符之间的差异。

答案 2 :(得分:1)

&&是一个布尔运算符,而&是一个按位运算符。

&是两个整数的操作。示例:1100 & 1001 = 1101,所以12 & 9 = 13

&&仅检查两个(左和右)值是否为TRUE(即非零)。

1 & 2例如0,因为二进制1和2是0.示例:01 & 10 = 00

虽然1 && 2TRUE && TRUE类似,但也等于true。因此,对于&&,左右两个值都被转换为&#34;首先是布尔表达式,然后进行比较。

另外,请不要忘记编译器能够短路&&个表达式。像这样:

bool variable = isValid && compareSomething()

不评估正确的值,因为它不需要。只要variable为真,第一个已经清楚地表明isValidisValid

Read more