switch 语句:必须 default 是最后一种情况吗? [英] Switch statement: must default be the last case?

查看:12
本文介绍了switch 语句:必须 default 是最后一种情况吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的 switch 语句:

switch(值){情况1:返回 1;默认:价值++;//跌落案例2:返回值 * 2;}

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


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

解决方案

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

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

<块引用>

任何语句前面都可以有一个将标识符声明为的前缀标签名称.标签本身就可以不改变控制流,这继续畅通无阻地穿过它们.

编辑:开关内的代码没什么特别的;它是 if 语句中的普通代码块,带有额外的跳转标签.这解释了失败行为以及为什么需要 break.

6.8.4.2.7甚至给出了一个例子:

开关 (expr){诠释 i = 4;f(i);案例0:我=17;/*进入默认代码*/默认:printf("%d
", i);}

<块引用>

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

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

<块引用>

6.8.4.2.3 每个案例标签的表达式应为整数常量表达和没有两种情况相同的常量表达式switch 语句应具有相同的转换后的价值.可能有一个开关中最多有一个默认标签声明.

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

<块引用>

6.8.4.2.5 整数提升在控制上执行表达.中的常量表达式每个案例标签都转换为提升型控制表达.如果换算值与晋升者相匹配控制表情,控制跳跃到匹配后的语句案例标签.否则,如果有默认标签,控制跳转到标记的声明.如果没有转换case 常量表达式匹配和没有默认标签,没有部分开关体被执行.

Consider the following switch statement:

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

This code compiles, but is it valid (= defined behavior) for C90/C99? I have never seen code where the default case is not the last case.

EDIT:
As Jon Cage and KillianDS write: this is really ugly and confusing code and I am well aware of it. I am just interested in the general syntax (is it defined?) and the expected output.

解决方案

The C99 standard is not explicit about this, but taking all facts together, it is perfectly valid.

A case and default label are equivalent to a goto label. See 6.8.1 Labeled statements. Especially interesting is 6.8.1.4, which enables the already mentioned Duff's Device:

Any statement may be preceded by a prefix that declares an identifier as a label name. Labels in themselves do not alter the flow of control, which continues unimpeded across them.

Edit: The code within a switch is nothing special; it is a normal block of code as in an if-statement, with additional jump labels. This explains the fall-through behaviour and why break is necessary.

6.8.4.2.7 even gives an example:

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

In the artificial program fragment the object whose identifier is i exists with automatic storage duration (within the block) but is never initialized, and thus if the controlling expression has a nonzero value, the call to the printf function will access an indeterminate value. Similarly, the call to the function f cannot be reached.

The case constants must be unique within a switch statement:

6.8.4.2.3 The expression of each case label shall be an integer constant expression and no two of the case constant expressions in the same switch statement shall have the same value after conversion. There may be at most one default label in a switch statement.

All cases are evaluated, then it jumps to the default label, if given:

6.8.4.2.5 The integer promotions are performed on the controlling expression. The constant expression in each case label is converted to the promoted type of the controlling expression. If a converted value matches that of the promoted controlling expression, control jumps to the statement following the matched case label. Otherwise, if there is a default label, control jumps to the labeled statement. If no converted case constant expression matches and there is no default label, no part of the switch body is executed.

这篇关于switch 语句:必须 default 是最后一种情况吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆