C言語には三つの主要なループ構造があります:for、while、およびdo-while。これらの登場は、繰り返し計算を実現し、データ構造の巡回を容易にし、配列の処理を自動化する必要性に関連しています。初めてループの構文は初期プログラミング言語(ALGOL、FORTRAN)で登場し、C言語の構文に適応されて可読性とフロー管理を向上させました。
歴史的背景
最初はプログラマーはラベルとgotoを使用して繰り返し動作を整理していましたが、すぐに複雑なコード(スパゲッティコード)になってしまいました。構造的ループの導入(Cでは1972年から)は、繰り返しとプログラムロジックの記述方法を統一することを可能にしました。
問題
ループの主な目的は、特定の動作が何回繰り返されるべきかを決定し、ループからの脱出をどのように制御するかを定義することです。事前に繰り返しの回数がわかっているか、少なくとも一度はボディを実行する必要があるか、脱出条件を事前に計算する必要があるかに応じて、ループのタイプを適切に選ぶことが重要です。
解決策
コードの例:
#include <stdio.h> int main() { int i = 0; // whileループの例 while (i < 3) { printf("while: %d\n", i); i++; } // forループの例 for (int j = 0; j < 3; j++) { printf("for: %d\n", j); } // do-whileループの例 int k = 0; do { printf("do-while: %d\n", k); k++; } while (k < 3); return 0; }
重要な特徴:
while(1)とfor(;;)の違いは何ですか?無限ループにはどちらを使うべきですか?
答え:どちらの形式も無限ループを作成し、同じマシンコードに変換されるため、パフォーマンスには違いはありません。通常、for(;;)を使用して、初期化、脱出条件、ステップが期待されないことを明示的に示します。
for(;;) { // 無限ループ } // または while(1) { // 無限ループ }
forのボディ内でループ変数を変更することはできますか?そうした場合に何が起こりますか?
答え:forループのボディ内でカウンタ変数(例えば、i++)を変更すると、イテレーションの数が予測できないものになります。これらの変更は、リーダーを混乱させ、デバッグを困難にします。
for (int i = 0; i < 10; i++) { printf("%d\n", i); i += 2; // 標準的でないステップの変更! }
ループのボディを空にした場合、何が起こりますか?どのような場合に意味がありますか?
答え:空のループボディは許可されており、イベントの発生を待ったりデータを準備するために使用されます:
while(*src++ = *dst++); // '\0'文字までの文字列コピー
ネガティブケース
プロジェクトでは、ボディ内でカウンタ変数を変更するforを使用し、処理された要素の数が誤り、バグやデバッグの困難に繋がりました。
長所:
短所:
ポジティブケース
カウンタを外部で変更せずに固定長の配列を巡回するためのforの使用:
長所:
短所: