《第九课——C语言判断:从Java的“文明裁决“到C的“原始决斗“——if/else的生死擂台与switch的轮盘赌局》
引言:
当Java程序员还在用优雅的switch
枚举时,C语言已经掏出了条件判断的骨棒和石斧!本文将用角斗场比喻带你体验C的判断江湖:从if
的陷阱狩猎、else if
的悬崖对决,到switch
的死亡轮盘赌。揭露浮点数比较的流沙陷阱、悬空else的视觉骗局,以及那些让Java的instanceof
无地自容的指针判空硬核操作。
一、判断基础:C的"石斧" vs Java的"精钢剑"
1. if语句:生存还是毁灭?
// C:原始骨棒级判断
int hunger = 80;
if (hunger > 75) { printf("快去找食物!\n");
}
Java:语法相同但更安全(条件必须为布尔值)
boolean isHungry = (hunger > 75);
if (isHungry) { // 必须布尔值! System.out.println("快去找食物!");
}
2. if-else:悬崖二选一
if (hunger > 90) { printf("吃人!\n");
} else if (hunger > 75) { printf("狩猎野猪!\n");
} else { printf("摘果子\n");
}
危险差异:C的条件中可包含赋值(血泪陷阱!)
if (hunger = 100) { // 赋值而非比较!恒为真 printf("饿死了\n"); // 永远执行!
}
二、深度陷阱:C判断的"死亡游戏"
1. 浮点数比较:流沙陷阱
float f1 = 0.1 + 0.2;
float f2 = 0.3;
if (f1 == f2) { // 可能为假!浮点精度问题 printf("数学没白学!\n");
}
安全姿势:
#include <math.h>
if (fabs(f1 - f2) < 0.00001) { // 设定误差阈值 printf("近似相等!\n");
}
2. 悬空else:视觉骗局
if (hunger > 50) if (hunger > 75) printf("狩猎\n");
else // 这个else属于内层if! printf("摘果子\n"); // hunger<=75但>50时执行
逃生指南:永远用{}
包裹代码块!
if (hunger > 50) { if (hunger > 75) { ... }
} else { ... } // 明确归属
3. switch:死亡轮盘赌
int weapon = 2;
switch (weapon) { case 1: printf("匕首\n"); break; // 必须break! case 2: printf("弓箭\n"); // 故意不break case 3: printf("投石\n"); break; // weapon=2时输出:弓箭→投石 default: printf("肉搏\n");
}
Java对比:
switch(weapon) { case 1: System.out.println("匕首"); break; // Java 12+支持箭头语法防止穿透 case 2 -> { System.out.println("弓箭"); } // 自动break
}
三、与Java的爆笑对比
场景1:布尔类型——贵族认证 vs 草根伪装
// Java:布尔贵族
boolean isRaining = true;
if (isRaining) { ... }
// C:整型草根(0为假,非0为真)
int isRaining = 1; // 1表示真
if (isRaining) { ... } // 合法但草率
// 优雅方式(C99):
#include <stdbool.h>
bool isSunny = false;
场景2:对象类型判断——魔法镜 vs 显微镜
// Java:instanceof魔法镜
Object obj = "Hello";
if (obj instanceof String) { String s = (String)obj; // 安全转换
}
// C:无运行时类型信息!需手动设计类型标签 (结构体 struct 和 共用体 union 后面讲解)
struct Object { enum { INT, FLOAT, STR } type; // 类型标签 union { int i; float f; char *s; } data;
}; struct Object obj;
obj.type = STR;
obj.data.s = "Hello"; if (obj.type == STR) { printf("%s", obj.data.s); // 安全访问
}
四、判断安全等级测评表
判断方式 | 可读性 | 灵活性 | 陷阱密度 | 适用场景 |
---|---|---|---|---|
if | ★★★☆☆ | ★★★★★ | ★★☆☆☆ | 简单条件 |
if-else 链 | ★★★☆☆ | ★★★★☆ | ★★★☆☆ | 多分支互斥 |
switch | ★★★★☆ | ★★☆☆☆ | ★★★★☆ | 离散整型值匹配 |
三元运算符 | ★★☆☆☆ | ★★★☆☆ | ★★★☆☆ | 简单条件赋值 |
Java专属:
instanceof
——类型安全等级★★★★★
五、使用场景与作死案例
✅ 正确姿势:
场景 | 推荐方式 | 案例 |
---|---|---|
范围判断 | if-else 链 | if(score>90) A; else if(score>80) B; |
离散值匹配 | switch | switch(weekday) { case MON: ... } |
简单条件赋值 | 三元运算符 | int max = (a>b)?a:b; |
指针安全性检查 | if 判空 | if (ptr != NULL) { *ptr=10; } |
💥 作死案例TOP3:
-
赋值代替比较
if (x = 0) { /* 永远不执行!但编译通过 */ } // 正确:if (x == 0)
-
浮点数精确比较
float f = 0.0; for (int i=0; i<10; i++) f += 0.1; if (f == 1.0) { /* 可能为假! */ }
-
switch的穿糖葫芦
switch (c) { case 'a': printf("A"); // 忘记break→继续执行case 'b'! case 'b': printf("B"); break; } // 输入'a'输出:AB
六、总结:C判断生存法则
Java哲学:类型安全第一,避免低级错误
C哲学:自由即危险——给你石斧,但小心砍到自己脚!
彩蛋:判断迷惑行为大赏
// C:在条件中声明变量(C99特性)
if (int i = some_function()) { // i在此作用域内,且值非0则进入
}
// Java:无法在条件内声明变量,但可这样:
if ((i = someFunction()) != 0) { /* 作用域外仍可见i! */ }
趣评:C的条件像瑞士军刀——功能多但易割手;Java的条件像安全剪刀——安全但剪不了钢铁!