考虑下面的switch语句:
switch( value )
{
case 1:
return 1;
default:
value++;
// fall-through
case 2:
return value * 2;
}
此代码编译,但它是有效的(=定义的行为)C90/C99?我从未见过默认情况不是最后一个情况的代码。
编辑:
正如Jon Cage和KillianDS所写的:这真的是丑陋而令人困惑的代码,我很清楚这一点。我只对通用语法(有定义吗?)和预期的输出感兴趣。
C99标准没有明确说明这一点,但综合所有事实来看,它是完全有效的。
case和default标签等同于goto标签。参见6.8.1标记语句。特别有趣的是6.8.1.4,它启用了前面提到的达夫装置:
任何语句前都可以加上
声明标识符为的前缀
标签名称。标签本身
不改变流控制,其中
继续畅通无阻地穿过它们。
编辑:开关内的代码没有什么特别的;它是一个正常的if语句代码块,带有额外的跳转标签。这解释了跌倒行为,以及为什么休息是必要的。
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各大小写标号的表达式为整数常数
表达和没有两种的情况
常数表达式是一样的
开关语句也应相同
转换后的值。可能有
一个交换机最多只能有一个默认标签
声明。
所有的情况都被评估,然后它跳转到默认标签,如果给定:
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语句中没有定义的顺序。你可以把这些情况看作一个命名标签,一个goto标签。与人们在这里的想法相反,在值2的情况下,默认标签不会跳转到。为了用一个经典的例子来说明,这里是Duff的设备,它是C语言中switch/case的极端代表。
send(to, from, count)
register short *to, *from;
register count;
{
register n=(count+7)/8;
switch(count%8){
case 0: do{ *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
}while(--n>0);
}
}