为什么转换语句需要rest?

给定一个简单的switch语句

switch (int) { case 1 : { printf("1\n"); break; } case 2 : { printf("2\n"); } case 3 : { printf("3\n"); } } 

案例2中没有中断陈述,意味着在案例3的代码中将继续执行。这不是偶然的, 它是这样devise的 为什么做出这样的决定? 这提供了什么好处与块有自动中断语义? 基本原理是什么?

许多答案似乎都把重点放在了作为要求断言的理由的能力上。

我相信这只是一个错误,很大程度上是因为当C被devise时,关于如何使用这些构造的经验并不那么多。

Peter Van der Linden在他的书“专家C程序devise”

我们分析了Sun C编译器资源,看看使用默认值的频率。 Sun ANSI C编译器前端有244个switch语句,每个语句平均有7个case。 在所有这些情况中仅有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标签堆叠 – 只要只有一个语句块)。 在C#中,您仍然可以将一个案例拖入另一个案例 – 只需使用goto跳转到下一个案例,就可以明确下降。

Java太糟糕了,没有趁机打破C语义。

在很多方面,c只是一个标准组装习语的简洁界面。 在编写跳转表驱动的stream程控制时,程序员可以select跳过或跳出“控制结构”,跳出需要明确的指令。

所以,c做同样的事情…

为了实现达夫的装置,显然是:

 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); } } 

如果案件被devise为隐含的突破,那么你就不可能犯下错误。

 case 0: case 1: case 2: // all do the same thing. break; case 3: case 4: // do something different. break; default: // something else entirely. 

如果交换机被devise为在每个案例之后隐含地突破,那么您将不会有select的余地。 开关盒结构的devise更加灵活。

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; 

为了让事情像:

 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标签,它自然而然地出现了。

当几个案例需要执行相同的代码(或者相同的代码)时,它消除了代码重复。

因为在汇编语言层面上,它并不关心你是否在每一个之间中断,或者没有零负载的情况下,为什么不允许他们,因为他们在某些情况下提供显着的优势。

正如许多人在这里指定的那样,允许一个代码块在多种情况下工作。 对于您的switch语句,这应该比您在示例中指定的“每个case的代码块”更为常见。

如果每个案例中有一个代码块没有经过转换,或许你应该考虑使用一个if-elseif-else块,因为这看起来更合适。