1. ホーム
  2. c

[解決済み] "break; "を "if "文から外す?

2022-02-19 11:49:11

質問内容

if文から抜け出せるか、クラッシュの原因にならないか?C言語を知り始めているのですが、これには賛否両論あるようです。最初の画像はC言語の本からです ("Head First C")、スニペットはハーバードのCSクラスのスタッフによって書かれたコードを示しています。実際どうなのか、C言語の標準と何か関係があるのでしょうか?

<ブロッククオート

は、if文を壊さない。

1990年1月15日、AT&Tの長距離電話システムがクラッシュし、6万人が電話を使えなくなった。 原因は?交換機で使われているC言語のコードを作っていた開発者が break から抜け出すために if ステートメントを使用します。 しかし break から抜け出さない。 if 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 は、最も近い場所にあるループやスイッチとのみ相互作用するため、それが for , while または do .. while という型があります。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の動作は似ています。

この通知で指摘されているプログラミングの間違いは、次のような誤解です。 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; の代わりに