为什么你的第二个 scanf 还没输入就直接跳过了?C语言输入缓冲区陷阱
写了几年 C 语言我发现很多刚入门的学弟学妹在处理多分支选择时全是一成不变的if-else if-else叠罗汉。每次看到那种嵌套了七八层的代码维护起来简直是折磨。其实当你在处理固定几个整数或者字符的条件判定时用switch-case结构会让代码干净得多。今天不聊教科书上那些死板的语法定义直接来看看这玩意在真实开发里怎么用以及在 Visual Studio 2013 环境下有哪些一碰就死锁的编译深坑。为什么不能用 switch 去判定浮点数我们先来死磕一个最基础的底层逻辑switch的括号里为什么只能放整型int、char、short等而绝对不能写double或float老实说我当年刚学 C 语言的时候也试过把浮点数塞进switch里结果 VS2013 直接一枪头拍出了error C2450: switch 表达式的类型“double”非法的编译报错。设计 C 语言的大佬们之所以这么规定是因为浮点数在内存里的存储天然就是不精确的。比如你在代码里写个0.1它在内存里可能实际是0.10000000149011612...。switch的本质是在内存里寻找精准的等值匹配如果允许浮点数进来两个看似相等的 case 可能会因为最后一位微小的精度偏差导致匹配失败。这种不确定性对编译器来说是个灾难。所以记住一条铁律只要涉及小数分支老老实实用if的范围判定switch只认整数。在 VS2013 下跑得通的真实业务代码我们拿一个学生成绩等级评定的常规业务来写个完整的例子。注意由于 VS2013 默认采用 C89 标志变量声明一定要老老实实写在函数块的最开头别习惯性地在中间临时定义否则会触发error C2143: 语法错误 : 缺少“;”(在“类型”的前面)。#includestdio.hintmain(){chargrade;intscore85;/* 将百分制分数折算成阶梯整数 */switch(score/10){case10:case9:gradeA;break;case8:gradeB;break;case7:gradeC;break;case6:gradeD;break;default:gradeF;break;}printf(最终评定等级为: %c\n,grade);return0;}这段代码里有个小技巧case 10:后面什么都没写直接顺延到了case 9:。这是故意利用了switch的特殊机制让 90 分和 100 分都走到 ‘A’ 等级的逻辑里。行后的break必须加不加的话程序会一直往下死穿这就是明天我们要单独拎出来抽打的“穿透效应”。避坑清单case 后面初始化变量引发的死锁级报错这是初学者最容易踩、而且死活想不通的一个大坑。有时候我们想在某个具体的case分支里定义一个临时变量存数据写出来的代码往往长这样switch(type){case1:inttemp_data100;/* 错误写法VS2013 会在这里爆 error C2143 */printf(%d,temp_data);break;default:break;}你一旦按 F5 编译VS2013 绝对会弹出error C2143或error C2141。为什么因为switch内部的所有case在内存视角里其实处于同一个作用域花括号范围内。你在case 1里定义了temp_data如果程序运行时直接跳到了default分支那么这个temp_data到底算分配了还是没分配编译器在做静态语法检查时无法容忍这种作用域内的二义性。正确做法有两种要么把temp_data提到整个switch语句的外面开头声明要么在case 1:后面强行加一个花括号{}把这个分支变成独立的局部作用域。我个人更推荐前者代码看起来更干净。标签#C语言#switch语句#VS2013#编译报错#零基础编程