if/else写错?面试官说:这种基础题都能翻车,后面不用考了 上周面了一个工作三年的候选人简历上写着熟悉C。我给他出了一道自认为很简单的题写一个函数根据输入的距离值判断机器人应该执行什么动作——距离小于1米停车1到5米减速大于5米正常行驶。他刷刷刷写完了。我一看逻辑是对的但有个细节if (distance 1.0) { stop(); } else if (distance 1.0 distance 5.0) { slow_down(); } else { normal_speed(); }我问他第二个条件里的distance 1.0能去掉吗他想了一下说能因为走到这里的时候distance肯定大于等于1了。那为什么要写为了……代码更清晰讲真这种问题我见过太多了。不是不会写if/else而是写出来的代码带着一种不信任语言特性的味道。好像不加那些冗余的条件程序就会跑偏似的。dangling elseC最经典的坑if/else看起来简单但C里有个历史悠久的坑叫dangling else悬挂else。看这段代码if (condition1) if (condition2) statement1; else statement2;这个else到底跟哪个if配对答案是跟最近的if配对也就是condition2。但很多人第一眼看上去会以为它跟condition1配对。我面试的时候特别喜欢拿这种代码出来让候选人分析执行流程。十个人里有六个会看错。怎么避免这个问题很简单加大括号。不管你的if/else后面只有一条语句还是多条语句都加上大括号。if (condition1) { if (condition2) { statement1; } else { statement2; } }这样写谁也不会看错。有些编码规范说单条语句可以不加括号我不同意。代码是给人看的不是给编译器看的。你省掉的那两个大括号可能让后面维护的人多花半小时理解逻辑。条件判断中的隐式转换陷阱if括号里的表达式最终会被转换成bool类型来判断真假。这个转换过程藏着不少坑。比如这个int error_code getErrorCode(); if (error_code -1) { handleError(); }看出问题了吗error_code -1是赋值不是比较。这个表达式的值是-1转换成bool是true所以handleError()永远会被执行。正确的写法应该是error_code -1。这种bug特别难发现因为代码能编译通过逻辑上也说得通。我以前也犯过这种错后来养成了一个习惯把常量写在左边。if (-1 error_code) { handleError(); }这样如果你少写了一个等号变成-1 error_code编译器会报错因为不能给常量赋值。这个技巧叫Yoda条件尤达条件因为读起来像尤达大师的说话方式——倒着说。不过说实话我现在不太用这个了。现代IDE都会警告你这种赋值和比较混淆的问题靠编译器检查就够了。还有一个常见的坑指针判断。if (ptr) { // ptr不为空 }这个写法没问题。我个人更喜欢直接写if (ptr)简洁明了。但在团队里大家统一风格就好没必要在这个问题上较真。switch vs if/else什么时候该用哪个条件判断多了就会面临一个选择用if/else链还是switch// 方式一if/else链 if (state IDLE) { handleIdle(); } else if (state MOVING) { handleMoving(); } else if (state ERROR) { handleError(); } // 方式二switch switch (state) { case IDLE: handleIdle(); break; case MOVING: handleMoving(); break; case ERROR: handleError(); break; }很多人说switch效率更高因为编译器会优化成跳转表。这话对也不全对。如果你的case是连续的整数比如0、1、2、3编译器确实会生成跳转表时间复杂度是O(1)。但如果你的case是分散的比如10、100、1000编译器可能还是会生成if/else链这时候效率跟if/else没区别。所以在机器人状态机这种场景下如果状态值是连续的enum用switch确实更合适。代码也更清晰一眼就能看出所有可能的分支。但有个坑必须注意break。switch (state) { case IDLE: handleIdle(); case MOVING: handleMoving(); break; }如果state是IDLEhandleIdle()执行完后会继续执行handleMoving()因为没有break。这叫fall-through贯穿。有时候这是bug有时候这是故意的设计。但大多数情况下你都需要在每个case后面加break。我见过一个实习生写的代码switch里忘了写break结果机器人每次进入IDLE状态都会莫名其妙地开始移动。查了一下午才发现问题。还有个细节switch里的变量定义。switch (state) { case IDLE: int x 10; // 编译错误 handleIdle(); break; }这样写会编译错误因为x的作用域跨越了整个switch但它的初始化只在IDLE分支里。解决办法是加大括号switch (state) { case IDLE: { int x 10; handleIdle(); break; } }这种细节课本上不一定讲但实际开发中真的会遇到。条件判断的性能考量在机器人系统里有些代码路径对实时性要求很高比如控制循环。这时候条件判断的性能就不能忽视了。if/else链的问题在于如果条件很多最坏情况下要判断很多次才能找到匹配的分支。而switch在case连续的情况下一次跳转就能到位。但还有一种情况如果你的条件是范围判断比如距离小于1米1到5米大于5米switch就用不了了因为它只能判断相等。这时候怎么办一种优化方法是把最可能的分支放在前面。机器人大部分时间都在正常行驶那就把大于5米的判断放第一个if (distance 5.0) { normal_speed(); } else if (distance 1.0) { slow_down(); } else { stop(); }这样大部分情况下第一次判断就能命中减少了分支预测失败的概率。不过说实话这种优化在大多数场景下没必要。现代CPU的分支预测器很强你代码里那点if/else的差别根本感觉不出来。真正需要优化的是那些每秒钟要执行上万次的代码路径比如控制循环里的计算。其他地方代码可读性比性能重要得多。给正在准备面试的你一点建议if/else真的是最基础的语法了。但基础的东西往往最能看出一个人的编程习惯。我面试的时候看候选人写if/else主要看几点大括号加不加、条件判断有没有冗余、switch有没有break、变量作用域对不对。这些细节做好了说明这个人写过规范的代码有工程素养。怎么提高我的建议是去看看开源的机器人代码比如ROS2的导航栈、SLAM算法看看人家是怎么写条件判断的。然后对比自己的代码看看有哪些地方可以改进。最的是养成加大括号的习惯。不管你的if后面只有一条语句还是十条语句都加上大括号。这个习惯一旦养成能帮你避免很多低级bug。如果这篇文章对你有帮助欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。「机器人软件开发面试·从入门到精通」连载系列上一篇第2篇 运算符与表达式——让数据动起来的基本语法 下一篇预告第4篇 循环结构for/while——机器人数据采集的重复逻辑有任何问题欢迎评论区留言我会尽量回复。