你能否突破if语句或是否会导致崩溃?我开始熟悉C,但这似乎有争议。第一张图片来自C上的一本书 (“Head First C”)和该片段显示了哈佛大学CS班级工作人员编写的代码。究竟是怎么回事并且与C标准有关?
如果陈述,休息不会中断。
1990年1月15日,AT& T的长途电话系统崩溃,6万人失去了电话服务。原因?处理交换中使用的C代码的开发人员试图使用
break
来突破if
语句。但是break
并没有突破if
。相反,该程序跳过了整段代码,并引入了一个错误,该错误在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");
答案 0 :(得分:34)
break
仅与最近的封闭循环或切换进行交互,无论是for
,while
还是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;
不同之处在于,continue
和break
与编译器自动放置的虚拟标签交互。这类似于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
。预期的功能将使用if (!G) H;
。
答案 1 :(得分:2)
这实际上是break
语句的常规用法。如果break
语句未嵌套在if
块中,则for
循环只能执行一次。
MSDN将此列为break
语句的example。
答案 2 :(得分:1)
如前所述, break-statement 只能 开关和循环。这是实现所要求的另一种方式。我正在复制 https://stackoverflow.com/a/257421/1188057正如其他人没人提到的那样。这只是一个涉及do-while循环的技巧。
do {
// do something
if (error) {
break;
}
// do something else
if (error) {
break;
}
// etc..
} while (0);
虽然我更喜欢使用 goto-statement 。
答案 3 :(得分:0)
我认为问题有点模糊 - 例如,它可以被解释为关于编程循环内部if
的最佳实践的问题。所以,我试着用这个特别的解释来回答这个问题。
如果你在循环中有if
,那么在大多数情况下,你想知道循环是如何结束的 - 它是否已被打破&#34;由if
或者它结束了#34;自然而然地#34;?因此,您的示例代码可以通过以下方式进行修改:
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
}
在这种情况下,您可以清楚地看到(只是查看循环&#34;标题&#34;)此循环可以过早结束。如果循环体是由其他人编写的多页文本,那么您要感谢其作者节省您的时间。
<强>更新强>
感谢SO - 它刚刚建议已经回答question关于AT&amp; T电话网络在1990年崩溃的问题。这是关于C创作者使用单个保留字的风险决定{ {1}}从两个循环和break
退出。
无论如何,这个解释并没有跟原始问题中的示例代码一致,所以我将答案保留原样。