C/C++の無限ループ [閉店]のお知らせ
質問
無限ループを行うにはいくつかの可能性がありますが、ここでは私が選んだものをいくつか紹介します。
-
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(;;)
の意味を知っているのであれば、これ以上読みやすくする意味はありません - それはすでに読みやすくなっているのです。
関連
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++
-
[解決済み] jQueryの各ループから抜け出すには?
-
[解決済み] JavaScriptのオブジェクトをループスルーまたは列挙するにはどうすればよいですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] オブジェクトをメンバーとして、プレーンなJavaScriptオブジェクトをループさせる方法
-
[解決済み] Javaでenumを繰り返し処理するためのforループ
-
[解決済み] C#のループ - breakとcontinue
-
[解決済み] Bashでの単一行whileループの構文
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】識別子 "string "は未定義?
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] for(;)」は「while(true)」より速い?もしそうでないなら、なぜ人々はそれを使うのでしょうか?
-
[解決済み] C#の無限ループはfor(;;)とwhile(true)のどちらが正しいか?[クローズド]