小编典典

switch 语句:必须 default 是最后一种情况吗?

all

考虑以下switch语句:

switch( value )
{
  case 1:
    return 1;
  default:
    value++;
    // fall-through
  case 2:
    return value * 2;
}

此代码可以编译,但对于 C90/C99 是否有效(= 定义的行为)?我从未见过 默认 情况不是最后一种情况的代码。

编辑:
正如 Jon CageKillianDS 所写:这真的是丑陋和令人困惑的代码,我很清楚这一点。我只对一般语法(是否已定义?)和预期输出感兴趣。


阅读 125

收藏
2022-07-07

共1个答案

小编典典

C99 标准对此没有明确说明,但综合所有事实,它是完全有效的。

Acasedefaultlabel 等价于一个goto标签。请参见 6.8.1 标记语句。特别有趣的是 6.8.1.4,它启用了已经提到的
Duff 设备:

任何语句前面都可以有一个前缀,将标识符声明为标签名称。标签本身不会改变控制流,控制流在它们之间继续畅通无阻。

编辑 :开关中的代码没什么特别的;它是一个普通的代码块,就像在-
语句中if一样,带有额外的跳转标签。这解释了失败行为以及为什么break是必要的。

6.8.4.2.7 甚至给出了一个例子:

switch (expr) 
{ 
    int i = 4; 
    f(i); 
case 0: 
    i=17; 
    /*falls through into default code */ 
default: 
    printf("%d\n", i); 
}

在人工程序片段中,标识符为 i 的对象具有自动存储持续时间(在块内)但从未初始化,因此如果控制表达式具有非零值,则对 printf
函数的调用将访问一个不确定的值。同样,无法调用函数 f。

case 常量在 switch 语句中必须是唯一的:

6.8.4.2.3 每个case标签的表达式应为整数常量表达式,同一switch语句中的任何两个case常量表达式转换后的值不得相同。switch
语句中最多可以有一个默认标签。

评估所有案例,然后跳转到默认标签,如果给出:

6.8.4.2.5 整数提升在控制表达式上执行。每个 case
标签中的常量表达式都转换为控制表达式的提升类型。如果转换后的值与提升的控制表达式的值匹配,则控制跳转到匹配的 case
标签后面的语句。否则,如果有默认标签,则控制跳转到有标签的语句。如果没有转换后的 case 常量表达式匹配并且没有默认标签,则不会执行 switch
主体的任何部分。

2022-07-07