跳到主要内容

C 语言类型转换

& vs. &&

& 是位运算符,&& 是布尔运算符。0b010 & 0b101 => 0b000,但是用 && 计算时,结果就是 TRUE 了,因为两边都不是 FALSE

但实际上很容看岔了:

#include <stdio.h>

int main() {
if (1 == 1 & 2) { printf("True\n"); } else { printf("False\n"); }
if (1 == 1 && 2) { printf("True\n"); } else { printf("False\n"); }
if (2 == 2 & 1) { printf("True\n"); } else { printf("False\n"); }
if (2 == 2 && 1) { printf("True\n"); } else { printf("False\n"); }
return 0;
}

在 Compiler Explorer 中打开

第一个输出的结果是 FALSE,这符合我们的预期吗?难道不应该全部打印 TRUE 吗?我相信,越是老油条,约容易疏忽,特别是现实的业务代码肯定不是直接用数字,而是使用枚举值或者函数返回值。好在现在的 lint 工具,能提醒我们是不是漏写了一个 &

但如果 & 的左右都是布尔值,那么两者是不是等价呢?不是的,看下面的代码:

#include <stdio.h>

int foo() {
printf("foo\n");
return 0;
}

int bar() {
printf("bar\n");
return 2;
}

int baz() {
printf("baz\n");
return 3;
}

int main() {
int num = foo() & (bar() * baz());
}

在 Compiler Explorer 中打开

首先,这段代码的输出是foo\nbar\nbaz,可能我们会以为 barbaz 因为 () 运算优先而优先打印,当然是另外一个陷阱;然后思考下如果将 & 替换成 &&,结果是什么?结果只有一个 foo,也就是 () 里的表达式并没有被执行。这就是 &&& 的一大区别,即后者具有提前返回的“短路”能力。相对应的,|| 也能在左侧值为真时短路。利用短路特性,可以写出 if (ptr && *ptr > 3) 这样的代码,避免 NULL 参与运算。