Answers:
许多答案似乎把重点放在为告吹的能力理由要求该break
陈述。
我认为这只是一个错误,主要是因为在设计C时,关于如何使用这些构造的经验并不多。
彼得·范德·林登(Peter Van der Linden)在他的《专家C编程》一书中阐述了这一点:
我们分析了Sun C编译器的源代码,以查看使用默认落空率的频率。Sun ANSI C编译器前端有244个switch语句,每个语句平均有7种情况。在所有这些情况中,只有3%发生失败。
换句话说,正常的切换行为有97%的时间是错误的。它不仅仅在编译器中-相反,在此分析中使用掉线的情况通常是发生在编译器中的情况比其他软件中更常见,例如,当编译可具有一个或两个操作数的运算符时:
switch (operator->num_of_operands) { case 2: process_operand( operator->operand_2); /* FALLTHRU */ case 1: process_operand( operator->operand_1); break; }
案例失败率被广泛认为是一种缺陷,以至于甚至有一个特殊的注释约定,如上所示,这告诉皮棉“这确实是希望失败率的3%案例之一。”
我认为对于C#来说,在每个case块的末尾都需要一个显式的jump语句是一个好主意(尽管仍然允许堆叠多个case标签-只要只有一个语句块)。在C#中,您仍然可以将一种情况归结为另一种情况-您只需要使用goto
。
太糟糕了,Java没有抓住机会打破C语义。
从很多方面来说,c仅仅是标准汇编惯用法的干净接口。在编写由跳转表驱动的流控制时,程序员可以选择掉入或跳出“控制结构”,而跳出则需要一条明确的指令。
所以,c做同样的事情...
NULL
。(下一条评论继续。)
NUL
结尾的字符串几乎是有史以来最糟糕的想法。
DO
循环的设计更糟。
要实现Duff的设备,显然:
dsend(to, from, count)
char *to, *from;
int count;
{
int 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);
}
}
如果案例被设计为隐式中断,那么您就不会陷入困境。
case 0:
case 1:
case 2:
// all do the same thing.
break;
case 3:
case 4:
// do something different.
break;
default:
// something else entirely.
如果开关被设计为在每种情况下都会隐式爆发,那么您将没有选择。开关盒结构的设计方式使其更加灵活。
switch语句中的case语句只是标签。
当您打开一个值时,switch语句实际上会转到具有匹配值的标签。
这意味着必须使用中断,以避免传递到下一个标签下的代码。
至于为什么以这种方式实现它的原因-switch语句的掉线性质在某些情况下会很有用。例如:
case optionA:
// optionA needs to do its own thing, and also B's thing.
// Fall-through to optionB afterwards.
// Its behaviour is a superset of B's.
case optionB:
// optionB needs to do its own thing
// Its behaviour is a subset of A's.
break;
case optionC:
// optionC is quite independent so it does its own thing.
break;
break
需要的地方。2)如果case语句的顺序更改,则失败可能导致运行错误的case。因此,我发现C#的处理要好得多(goto case
除空的大小写标签外,这对于掉线很明显)。
break
在C#中忘记-最简单的一种方法是,当您不想case
做任何事情而忘记添加一个break
(也许您被解释性注释中的内容包住了,或者被某些东西打断了)其他任务):执行将落在case
下面。2)鼓励goto case
是鼓励使用非结构化的“意大利面条”编码-您可能会遇到偶然的循环(case A: ... goto case B; case B: ... ; goto case A;
),尤其是当个案在文件中分开且难以合并时。在C ++中,直通是本地化的。
允许这样的事情:
switch(foo) {
case 1:
/* stuff for case 1 only */
if (0) {
case 2:
/* stuff for case 2 only */
}
/* stuff for cases 1 and 2 */
case 3:
/* stuff for cases 1, 2, and 3 */
}
将case
关键字视为goto
标签,它自然而然地出现了。
if(0)
在第一种情况的末尾那是邪恶的,只有在目标是混淆代码的情况下才应使用。
当几种情况需要执行相同的代码(或依次执行相同的代码)时,它消除了代码重复。
由于在汇编语言级别上,无论您是否在每个语言之间都中断,都不会在乎,总而言之,零失误案例的开销为零,所以为什么不让他们这样做,因为它们在某些情况下具有明显的优势。
我碰巧遇到了将向量中的值分配给结构的情况:必须以这种方式完成:如果数据向量短于结构中数据成员的数量,则其余成员将保留在它们的默认值。在那种情况下,省略break
是非常有用的。
switch (nShorts)
{
case 4: frame.leadV1 = shortArray[3];
case 3: frame.leadIII = shortArray[2];
case 2: frame.leadII = shortArray[1];
case 1: frame.leadI = shortArray[0]; break;
default: TS_ASSERT(false);
}
正如这里许多人所指定的,它允许单个代码块在多种情况下都可以工作。这应该与您在示例中指定的“每个案例的代码块”相比,对于switch语句,是更常见的情况。
如果每种情况都有一个代码块而不会掉线,则也许应该考虑使用if-elseif-else块,因为这似乎更合适。