编程嵌入式C程序员

请讲述一下C语言中switch语句是如何工作的。什么时候使用它比较合适,有哪些限制,关于隐含的陷阱和可移植性需要知道什么?

用 Hintsage AI 助手通过面试

回答。

问题背景:

switch语句被引入C语言中,以方便根据表达式的值在多个分支之间分配控制。这是一个大型if-else链的替代方案,广泛应用于处理命令、状态和枚举值。

问题:

switch语句的主要危险在于遗忘了break语句、意外地发生了"fallthrough"、在块内声明的变量造成的复杂性,以及表达式的类型必须是整数。

解决方案:

为了安全使用:

  • 始终使用break(或者用注释明确标记需要fallthrough);
  • 不要使用与int不兼容的类型;
  • 在default分支中处理所有未在case中定义的值;
  • 变量仅在case结构外或{}范围内声明。

代码示例:

#include <stdio.h> void print_day(int day) { switch (day) { case 1: printf("Monday "); break; case 2: printf("Tuesday "); break; case 3: printf("Wednesday "); break; case 4: printf("Thursday "); break; case 5: printf("Friday "); break; case 6: case 7: printf("Weekend "); break; default: printf("Unknown day "); } }

关键特点:

  • case目标必须是唯一的。
  • 值必须是常量,通常是字面量或枚举。
  • 从一个case“掉落”到另一个case是自动发生的,没有break。

误导性问题。

可以在switch表达式中使用float类型吗?

不可以。C语言标准要求switch表达式必须是整型或可转换为整型的类型(char、short、int、long、enum等)。

如果交换case的位置,顺序会影响逻辑吗?

switch中case的声明顺序不会影响找到所需值的过程。代码从匹配的case开始执行,直到第一个break。但在没有break(fallthrough)的情况下顺序是有影响的。

可以在没有大括号的case中声明变量吗?

不可以。如果在case之后声明变量而没有额外的{}块,会导致编译错误。正确的方式是:

switch (x) { case 1: { int y = 0; break; } }

常见错误和反模式

  • 忘记在case块末尾使用break,导致多余的副作用。
  • 不使用default,导致维护更加困难。
  • 在case标签后声明变量而没有{}块。
  • 使用不是编译时常量的值。

生活中的例子

消极案例

在一个大型项目中,程序员在一个case后忘记了break,因此误执行了多个分支。这个bug只被用户发现。

优点:

  • 代码更少,编写速度更快。

缺点:

  • 逻辑被破坏,用户得到了错误的结果,调试花费了很长时间。

积极案例

在需要fallthrough的情况下,使用注释标记的fallthrough进行说明,所有关键的case都有break或return,default中输出警告。

优点:

  • 代码更易读,bug更少。
  • 行为对每个阅读者都是透明的。

缺点:

  • 需要细心维护每个分支。