1. ホーム
  2. c++

C/C++の無限ループ [閉店]のお知らせ

2023-08-28 07:20:33

質問

無限ループを行うにはいくつかの可能性がありますが、ここでは私が選んだものをいくつか紹介します。

  • for(;;) {}
  • while(1) {} / while(true) {}
  • do {} while(1) / do {} while(true)

どのような形式を選べばよいのでしょうか?また、最近のコンパイラは、中間と最後の文の違いを判断するのでしょうか、それとも無限ループであることを認識して、チェック部分を完全にスキップするのでしょうか?

編集:言及されているように、私は忘れていた goto を忘れてしまいましたが、これは私がコマンドとして全く好きではないという理由からです。

Edit2: kernel.orgから取得した最新バージョンでいくつかのgrepをしてみました。私は、(少なくともカーネル内では) 時間の経過とともにあまり何も変わっていないように見えます。

どのように解決するのですか?

この質問をするときの問題は、単に「私はこれが好きです」という主観的な答えがたくさん返ってくることです。 このような無意味な発言をする代わりに、個人的な意見ではなく、事実と参考資料でこの質問に答えるようにします。

経験を通じて、おそらく do-while の代替案 (および goto) は一般的に使用されないため、除外することから始めることができます。私は、専門家によって書かれた、実際の生産コードでそれらを見た記憶がありません。

その while(1) , while(true)for(;;) は、実際のコードによく見られる3つの異なるバージョンです。もちろん、これらは完全に等価であり、結果は同じマシンコードになります。


for(;;)

  • これは、永遠のループのオリジナルの正統な例です。古代の C のバイブルでは C プログラミング言語 by Kernighan and Ritchieに、そう書かれています。

    K&R 2nd ed 3.5:

    for (;;) {
    ...
    }
    
    

    は無限ループであり、ブレークやリターンなどの他の手段で解除されるものと思われます。 ブレークやリターンなどの他の手段で解除されると思われます。while と for のどちらを使うかは、主に個人の好みの問題です。 を使うかどうかは、個人の好みの問題です。

    長い間 (永遠ではありませんが)、この本は正典であり、C 言語のまさに定義であるとみなされていました。K&R は、この本の中で for(;;) の例を示すことに決めたので、少なくとも 1990 年の C 言語標準化までは、これが最も正しい形式と見なされていたことでしょう。

    しかし、K&R 自身はすでに好みの問題であることを表明しています。

    そして今日、K&R は C の標準的なリファレンスとして使用するには非常に疑問の多いソースです。数倍古い (C99 や C11 に対応していない) だけでなく、現代の C プログラミングではしばしば悪いとみなされる、あるいはあからさまに危険なプログラミング手法を説いているのです。

    しかし、K&R が疑わしいソースであるにもかかわらず、この歴史的側面が for(;;) .

  • に対する反論は for(;;) ループに対する反論は、それがやや不明瞭で読めないということです。このコードが何をするのか理解するためには、標準にある次のルールを知っている必要があります。

    ISO 9899:2011 6.8.5.3:

    for ( clause-1 ; expression-2 ; expression-3 ) statement
    
    

    /--/

    <ブロッククオート

    節-1も式-3も省略可能です。省略されたexpression-2 は0でない定数に置き換えられます。

    規格のこの文章からすると、forループの1番目と3番目の部分が省略されると2番目と違う扱いになるので、不明瞭なだけでなく、微妙だということにほとんどの人が同意すると思います。


while(1)

  • よりも読みやすい形式だと思われます。 for(;;) . しかし、これは、よく知られているものの、もう一つの不明瞭な規則に依存しています。すなわち、Cはすべての非ゼロ式をブール論理の真として扱います。すべての C プログラマはそのことに気付いているので、大きな問題にはならないでしょう。

  • この形式には1つの大きな、実際的な問題があります。それは、コンパイラがそれに対して "条件は常に真" または同様の警告を与える傾向があることです。これは良い警告であり、様々なバグを発見するのに役立つため、無効にはしたくない種類のものです。例えば、次のようなバグがあります。 while(i = 1) のようなバグは、プログラマが意図して while(i == 1) .

    また、外部の静的コード分析器は、"condition is always true"について泣き言を言いそうです。


while(true)

  • 作るには while(1) をさらに読みやすくするために、あるものは while(true) を使う人もいます。プログラマの間では、これが最も読みやすい形式であるということでコンセンサスが得られているようです。

  • しかし、この形式には while(1) と同じように、警告が表示されます。

  • C言語に関して言えば、この形式にはもう一つ欠点があり、それはマクロの true したがって、これをコンパイルするためには、ヘッダファイルをインクルードする必要があり、これは不都合かもしれません。C++では、これは問題ではありません。 bool がプリミティブなデータ型として存在し true は言語キーワードである。

  • この形式のさらに別の欠点は、C99 の bool 型を使用していることで、これは最新のコンパイラでしか使用できず、後方互換性がありません。繰り返しますが、これは C でのみ問題であり、C++ では問題ではありません。


では、どのフォームを使えばいいのでしょうか?どちらも完璧とは言えません。暗黒時代に K&R がすでに言っていたように、それは個人の好みの問題です。

個人的には、私はいつも for(;;) を使用します。これは、他の書式で頻繁に発生するコンパイラやアナライザの警告を避けるためです。しかし、おそらくもっと重要なのは、このためです。

もし、C 言語の初心者であっても が知っている その for(;;) が永遠のループを意味することを知っているのなら、あなたは誰のためにコードをより読みやすくしようとしているのでしょうか?

結局のところ、そういうことなのでしょう。もしあなたが、プログラミング言語の基本的な部分さえ知らない非プログラマーにとって、あなたのソースコードが読みやすくなるように努力しているとしたら、それは時間を浪費しているに過ぎないでしょう。彼らはあなたのコードを読むべきではないのです。

そして であるべきです。 を読んでいる人は、すでに for(;;) の意味を知っているのであれば、これ以上読みやすくする意味はありません - それはすでに読みやすくなっているのです。