C语言 “休息;” 出“if”语句?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24714287/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:12:57  来源:igfitidea点击:

"break;" out of "if" statement?

c

提问by Nick_Tsaftaridis

Can you break out of an if statement or is it going to cause crashes? I'm starting to acquaint myself with C, but this seems controversial. The first image is from a book on C ("Head First C") and the snippet shows code written by Harvard's CS classes staff. What is actually going on and has it something to do with C standards?

你能突破 if 语句还是会导致崩溃?我开始熟悉 C,但这似乎有争议。第一张图片来自一本关于 C 的书(“Head First C”),片段显示了由哈佛 CS 课程工作人员编写的代码。实际发生了什么,它与 C 标准有关吗?

breaks don't break if statements.

On January 15, 1990, AT&T's long-distance telephone system crashed, and 60,000 people lost their phone service. The cause? A developer working on the C code used in the exchanges tried to use a breakto break out of an ifstatement. But breaks don't break out of ifs. Instead, the program skipped an entire section of code and introduced a bug that interrupted 70 million phone calls over nine hours.

中断不会中断 if 语句。

1990 年 1 月 15 日,AT&T 的长途电话系统崩溃,60,000 人失去了电话服务。原因?一位在交易所使用的 C 代码上工作的开发人员试图使用 abreak来突破if语句。但是breaks 不会脱离ifs。相反,该程序跳过了整段代码并引入了一个错误,该错误在 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");

回答by Yann Vernier

breakinteracts solely with the closest enclosing loop or switch, whether it be a for, whileor do .. whiletype. It is frequently referred to as a goto in disguise, as all loops in C can in fact be transformed into a set of conditional gotos:

break仅与最接近的封闭循环或开关相互作用,无论它是forwhiledo .. while键入。它经常被称为变相的 goto,因为 C 中的所有循环实际上都可以转换为一组条件 goto:

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;

The difference is, continueand breakinteract with virtual labels automatically placed by the compiler. This is similar to what returndoes as you know it will always jump ahead in the program flow. Switches are slightly more complicated, generating arrays of labels and computed gotos, but the way break works with them is similar.

不同之处在于,continuebreak编译器自动放置的虚拟标签进行交互。这类似于return您所知道的,它总是会在程序流程中向前跳跃。开关稍微复杂一些,生成标签数组和计算得到的 goto,但 break 与它们的工作方式是相似的。

The programming error the notice refers to is misunderstanding breakas interacting with an enclosing block rather than an enclosing loop. Consider:

该通知所指的编程错误是误解break为与封闭块而不是封闭循环进行交互。考虑:

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

Someone thought, given such a piece of code, that Gwould cause a jump to I, but it jumps to J. The intended function would use if (!G) H;instead.

有人认为,给定这样一段代码,G会导致跳转到I,但它跳转到了J。预期的功能将if (!G) H;改为使用。

回答by Jonathan Mee

This is actually the conventional use of the breakstatement. If the breakstatement wasn't nested in an ifblock the forloop could only ever execute one time.

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

MSDN lists this as their examplefor the breakstatement.

MSDN 将此列为他们的语句示例break

回答by Abhinav

As already mentioned that, break-statementworks onlywith switchesand loops. Here is another way to achieve what is being asked. I am reproducing https://stackoverflow.com/a/257421/1188057as nobody else mentioned it. It's just a trick involving the do-while loop.

前面已经提到,突破语句工作交换机循环。这是实现所要求的另一种方法。我正在复制 https://stackoverflow.com/a/257421/1188057,因为没有人提到它。这只是一个涉及 do-while 循环的技巧。

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

Though I would prefer the use of goto-statement.

虽然我更喜欢使用goto-statement

回答by HEKTO

I think the question is a little bit fuzzy - for example, it can be interpreted as a question about best practices in programming loops with ifinside. So, I'll try to answer this question with this particular interpretation.

我认为这个问题有点模糊 - 例如,它可以被解释为一个关于if内部循环编程最佳实践的问题。所以,我将尝试用这种特殊的解释来回答这个问题。

If you have ifinside a loop, then in most cases you'd like to know how the loop has ended - was it "broken" by the ifor was it ended "naturally"? So, your sample code can be modified in this way:

如果你有if一个循环,那么在大多数情况下你想知道循环是如何结束的——它是被“打破”了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
}

The problem with this code is that the ifstatement is buried inside the loop body, and it takes some effort to locate it and understand what it does. A more clear (even withoutthe breakstatement) variant will be:

这段代码的问题在于该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
}

In this case you can clearly see (just looking at the loop "header") that this loop canend prematurely. If the loop body is a multi-page text, written by somebody else, then you'd thank its author for saving your time.

在这种情况下,您可以清楚地看到(仅查看循环“标题”)该循环可能会提前结束。如果循环正文是由其他人编写的多页文本,那么您会感谢它的作者节省了您的时间。

UPDATE:

更新:

Thanks to SO - it has just suggested the already answered questionabout crash of the AT&T phone network in 1990. It's about a risky decision of C creators to use a single reserved word breakto exit from both loops and switch.

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

Anyway this interpretation doesn't follow from the sample code in the original question, so I'm leaving my answer as it is.

无论如何,原始问题中的示例代码并没有遵循这种解释,所以我保留了我的答案。