考虑以下switch语句:
switch( value )
{
case 1:
return 1;
default:
value++;
// fall-through
case 2:
return value * 2;
}这段代码可以编译,但它对于C90/C99是否有效(=定义的行为)?我从未见过默认情况不是最后一种情况的代码。
编辑:
正如Jon Cage和KillianDS所写的:这是非常丑陋和令人困惑的代码,我很清楚这一点。我只对一般的语法感兴趣(它被定义了吗?)以及预期的输出。
发布于 2010-06-24 21:43:06
C99标准对此并不明确,但综合考虑所有事实,它是完全有效的。
case和default标签等同于goto标签。参见6.8.1标记语句。特别有趣的是6.8.1.4,它支持前面提到的Duff的设备:
任何语句前面都可以有一个前缀,该前缀将标识符声明为标签名称。标签本身不会改变控制流,控制流继续畅通无阻地通过它们。
编辑:开关中的代码没有什么特殊之处;它是一个普通的代码块,就像在if-statement中一样,带有附加的跳转标签。这解释了失败行为以及为什么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的对象以自动存储持续时间存在(在块内),但从未初始化,因此如果控制表达式具有非零值,则对
函数的调用将访问不确定的值。类似地,无法访问对函数f的调用。
case常量在switch语句中必须是唯一的:
6.8.4.2.3每个case标签的表达式必须是一个整数常量表达式,同一个switch语句中的两个case常量表达式转换后不能有相同的值。switch语句中最多只能有一个默认标签。
对所有案例进行评估,然后跳转到默认标签(如果给定):
6.8.4.2.5整数提升在控制表达式上执行。每个case标签中的常量表达式将转换为控制表达式的提升类型。如果转换后的值与升级的控制表达式的值匹配,则控制跳转到匹配的case标签后面的语句。否则,如果存在默认标签,则控制跳转到已标记的语句。如果没有匹配的转换后的case常量表达式,并且没有默认标签,则不执行开关主体的任何部分。
发布于 2010-06-24 21:05:46
case语句和default语句可以在switch语句中以任何顺序出现。default子句是一个可选子句,如果case语句中的常量都不匹配,则匹配该子句。
很好的例子:-
switch(5) {
case 1:
echo "1";
break;
case 2:
default:
echo "2, default";
break;
case 3;
echo "3";
break;
}
Outputs '2,default'如果您希望案例在代码中按逻辑顺序显示(如在中,不是说case 1、case 3、case 2/ default ),并且案例非常长,因此您不希望在默认情况下重复底部的整个case代码,这非常有用
发布于 2010-06-24 21:26:28
它是有效的,在某些情况下非常有用。
考虑以下代码:
switch(poll(fds, 1, 1000000)){
default:
// here goes the normal case : some events occured
break;
case 0:
// here goes the timeout case
break;
case -1:
// some error occurred, you have to check errno
}重点是上面的代码比级联的if更具可读性和效率。您可以将default放在末尾,但这是没有意义的,因为它会将您的注意力集中在错误情况而不是正常情况(这里是default情况)。
实际上,这不是一个很好的例子,在poll中,您知道最多可能发生多少个事件。我真正的观点是,有些情况下有一组定义的输入值,其中有“异常”和正常情况。如果把异常或正常情况放在前面会更好,这是一个选择问题。
在软件领域,我想到了另一种非常常见的情况:带有一些终结值的递归,,如果你可以用一个开关来表示它,default将是包含递归调用和终结值的区分元素(个别情况)的常见值。通常不需要关注终结值。
另一个原因是,情况的顺序可能会改变编译后的代码行为,这对性能很重要。大多数编译器生成编译后的汇编代码的顺序与代码在开关中出现的顺序相同。这使得第一种情况与其他情况非常不同:除第一种情况外,所有情况都将涉及跳转,这将清空处理器流水线。您可能会理解它就像分支预测器默认运行交换机中出现的第一个案例一样。如果一个案例比其他案例更常见,那么你有很好的理由把它作为第一个案例。
阅读评论这就是为什么最初的发帖者在阅读了Intel compiler Branch Loop reorganisation关于代码优化的文章后提出这个问题的具体原因。
然后,它将成为代码可读性和代码性能之间的某种仲裁。也许更好的做法是写一条评论,向未来的读者解释为什么一个案例最先出现。
https://stackoverflow.com/questions/3110088
复制相似问题