Github上翻到下面代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
enum Name {
Name_None = 0,
Name_A = 1,
Name_B = 2,
Name_C = 3,
};
void foo()
{
enum Name name = Name_C;
if (!name == Name_C) printf("1\n");
else printf("2\n");
}
void bar()
{
enum Name name = Name_C;
if (!name == Name_None) printf("1\n");
else printf("2\n");
}
void baz()
{
enum Name name = Name_None;
if (!name == Name_A) printf("1\n");
else printf("2\n");
}
int main()
{
foo();
bar();
baz();
return 0;
}
开发者本意是判断name是否等于某个枚举值,但由于运算符!的优先级高过==,表达式中enum转为int处理,对整形int取!的结果是0变为1,非0变为0,所以foo和bar的输出是对的,而baz的输出是错误的。
这是C语言自身的陷阱之一,没有清晰的规则和约束去减少优先级歧义,让开发者容易犯错。当然这位开发者把!写在开头,胆子也很大,同时下面原因导致他忽略了编译器警告:
- 习惯
- 编译选项关掉了此类警告
- 开发周期短、匆忙地做,而不是做好
- 维护既有代码时的传染
恰好最近翻到C专家编程,2.3.2谈到有些运算符的优先级是错误的,我也记不住优先级,但见过低级错误的毒打,所以建议做个蠢人,表达式中多使用括号,安心下班做玩具。