为什么转换语句需要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块,因为这看起来更合适。