“破坏;”出于“如果”陈述?

你能否突破if语句或是否会导致崩溃? 我开始熟悉C,但这似乎有争议。 第一张图片来自C(“Head First C”)上的一本书,该片段显示的是哈佛大学CS课程工作人员编写的代码。 究竟是怎么回事并且与C标准有关?

如果陈述,rest不会破坏。

1990年1月15日,AT&T的长途电话系统崩溃,6万人失去了电话服务。 原因? 处理交换中使用的C代码的开发人员试图使用break来打破if语句。 但是, if s没有突破s。 相反,该程序跳过了整段代码,并引入了一个错误,该错误在9个小时内中断了7000万个电话。

 for (size = 0; size < HAY_MAX; size++) { // wait for hay until EOF printf("\nhaystack[%d] = ", size); int straw = GetInt(); if (straw == INT_MAX) break; // add hay to stack haystack[size] = straw; } printf("\n"); 

break只与最近的封闭循环或开关交互,无论是forwhile还是do .. while类型。 它经常被称为变相goto,因为C中的所有循环实际上都可以转换为一组条件结果:

 for (A; B; C) D; // translates to A; goto test; loop: D; iter: C; test: if (B) goto loop; end: while (B) D; // Simply doesn't have A or C do { D; } while (B); // Omits initial goto test continue; // goto iter; break; // goto end; 

区别在于, continuebreak与编译器自动放置的虚拟标签交互。 这与return内容类似,因为您知道它将始终在程序流程中前进。 开关稍微复杂一些,生成标签数组和计算得到的数据,但是break与它们的工作方式是相似的。

通知所引用的编程错误是误解为与封闭块相互作用而不是封闭循环。 考虑:

 for (A; B; C) { D; if (E) { F; if (G) break; // Incorrectly assumed to break if(E), breaks for() H; } I; } J; 

有人认为,鉴于这样一段代码, G会导致跳转到I ,但它会跳到J 预期的function将使用if (!G) H; 代替。

这实际上是break语句的常规用法。 如果break语句没有嵌套在if块中, for循环只能执行一次。

MSDN将此列为break语句的示例 。

我认为问题有点模糊 – 例如,它可以被解释为关于编程循环中的最佳实践的问题, if在内部。 所以,我会试着用这个特别的解释回答这个问题。

如果你在一个循环中,那么在大多数情况下你想知道循环是如何结束的 – 它是否被“破坏”或者它是否“自然地”结束了? 因此,您可以通过以下方式修改示例代码:

 bool intMaxFound = false; for (size = 0; size < HAY_MAX; size++) { // wait for hay until EOF printf("\nhaystack[%d] = ", size); int straw = GetInt(); if (straw == INT_MAX) {intMaxFound = true; break;} // add hay to stack haystack[size] = straw; } if (intMaxFound) { // ... broken } else { // ... ended naturally } 

这段代码的问题在于if语句被隐藏在循环体内,并且需要花费一些精力来定位它并理解它的作用。 更明确(即使没有 break语句)变体将是:

 bool intMaxFound = false; for (size = 0; size < HAY_MAX && !intMaxFound; size++) { // wait for hay until EOF printf("\nhaystack[%d] = ", size); int straw = GetInt(); if (straw == INT_MAX) {intMaxFound = true; continue;} // add hay to stack haystack[size] = straw; } if (intMaxFound) { // ... broken } else { // ... ended naturally } 

在这种情况下,您可以清楚地看到(只是查看循环“标题”)此循环可能过早结束。 如果循环体是由其他人编写的多页文本,那么您要感谢其作者节省您的时间。

更新:

感谢SO - 它刚刚提出了关于AT&T电话网络在1990年崩溃的已经回答的问题 。这是关于C创建者使用单个保留字break退出循环和switch的风险决定。

无论如何,这个解释并没有遵循原始问题中的示例代码,因此我将保留我的答案。

如前所述, break-statement 仅适用switchloops 。 这是实现所要求的另一种方式。 我正在复制https://stackoverflow.com/a/257421/1188057,因为没有人提到它。 这只是一个涉及do-while循环的技巧。

 do { // do something if (error) { break; } // do something else if (error) { break; } // etc.. } while (0); 

虽然我更喜欢使用goto语句