我很难理解逻辑运算符在 C 中的工作原理。我已经了解位级运算符的工作原理,而且我还知道逻辑运算符将非零参数视为表示 TRUE,将零参数视为表示 FALSE
但是假设我们有 0x65 && 0x55。我不明白这个操作为什么以及如何给出 0x01。
我试图将其转换为二进制,但我无法弄清楚它是如何工作的
我很难理解逻辑运算符在 C 中的工作原理。我已经了解位级运算符的工作原理,而且我还知道逻辑运算符将非零参数视为表示 TRUE,将零参数视为表示 FALSE
但是假设我们有 0x65 && 0x55。我不明白这个操作为什么以及如何给出 0x01。
我试图将其转换为二进制,但我无法弄清楚它是如何工作的
&&
操作员:
如果左操作数和右操作数都不同于0
它的求值结果,1
否则它的求值结果为0
。
如果左操作数为0
,则不计算右操作数,结果为0
。
0x65 && 0x55
被评估为1
。
The&&
是一个逻辑AND
(而不是&
,它是按位 AND
的)。它只关心它的操作数是零/非零值。零被认为是false
,而非零被视为true
。
在您的情况下,两个操作数都是非零的,因此它们被视为true
,导致结果也是true
如此。C 表示true
为1
,说明您的操作的总体结果。
如果将操作更改为&
,您将获得按位操作。0x65 & 0x55
会给你一个结果0x45
。
C 和 C++ 具有三个逻辑运算符:逻辑非(!
)、逻辑与(&&
)和逻辑或(||
)。对于逻辑运算符,0
是 false 并且任何不为零的都是 true。此真值表说明了每个逻辑运算符的工作原理(将1
用于 for true
):
p q p && q p || q
= = ====== ======
1 1 1 1
1 0 0 1
0 1 0 1
0 0 0 0
真值表!
如下:
p !p
= ===
1 0
0 1
对于您的具体情况:
0x65 && 0x55
由于整个表达式的操作数0x65
和0x55
求值都求值为并因此扩展为,这适用于但链接线程中的其他答案也解释了它之前的应用方式。true
true
1
c99
c99
&&
是逻辑运算符,而不是位运算符。0x65 和 0x55 都为真,因此结果为真数。0x01 是一个真实的数字。
二进制表示仅对按位运算起作用。表达式0x65 & 0x55
等于0x45
。
任何计算结果为 0 的表达式都是假的。任何非零的表达式都是真的。所以 0x65 和 0x55 都是真的。
0x65 && 0x55
=> 真 && 真 => 真
我试图将其转换为二进制
这可能妨碍了理解。和 的确切位模式0x65
与0x55
所需结果完全无关,重要的是它们都是非零的。您可以考虑a = (0x65 && 0x55)
等效于以下内容:
if (0x65 != 0) goto condition_false;
if (0x55 != 0) goto condition_false;
a = 1;
goto condition_end;
condition_false:
a = 0;
condition_end:
给定的实现可能能够发出比这更有效的代码(尽管我已经看到了很多发出的代码,每个代码if ... goto
都是程序集中的测试和分支)。更高效的代码可能涉及一些位操作以避免分支。就此而言,在这个涉及常量的示例中,编译器可能只会发出a = 1;
.
不过,运算符的含义&&
是在条件执行方面。例如,如果您编写f() && g()
,则保证当f
返回 false 值时,g
不会调用。如果可以通过位旋转获得相同的结果,那么这可能是性能的奖励。
C 将大于零的值定义为“真”。由于 0x65 和 0x55 都符合此条件,因此结果也是 True - 在输出中为 1 - 或者在十六进制表示法中为 0x01。
您的代码的另一种编写方式是:
返回(0x65 为真)和(0x55 为真);
正如您所说,逻辑运算符将非零参数视为表示
(0x65 && 0x55) is equal as (0x65 > 0) && (0x55 > 0)
0x65 > 0 get true and 0x55 > 0 get true as well
So (0x65 && 0x55) is equal true && true = 1