“打破;”出于“if”声明?

时间:2014-07-12 13:50:37

标签: c

你能否突破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");

4 个答案:

答案 0 :(得分:34)

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。预期的功能将使用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退出。

无论如何,这个解释并没有跟原始问题中的示例代码一致,所以我将答案保留原样。