今回は、C言語の制御構造をif文とgoto文だけを使って書いてみる試みの2回目となります。前回は選択文を書き直しましたので、今回は繰り返し文の書き直しを行ってみたいと思います。
do文
C言語の繰り返し文の中では、do文は比較的目立たない存在かもしれません。しかし、コンピュータとの相性が最もよいのはdo文であり、効率のよいループを書きたいなら、do文を使えないかどうか検討してみるべきです。
それでは、早速ですが、次のコードを書き直すことにします。
0 1 2 3 4 5 6 7 8 9 |
do { ... /* 処理1 */ break; ... /* 処理2 */ continue; ... /* 処理3 */ } while (expr); |
上のコードを書き直すと、
0 1 2 3 4 5 6 7 8 9 10 |
Do: ... /* 処理1 */ goto Enddo; /* break; */ ... /* 処理2 */ goto Next; /* continue */ ... /* 処理3 */ Next: if (expr) goto Do; Enddo: |
のようになります。いきなりbreak文やcontinue文も入れてしまったのでやや煩雑になりましたが、基本はループの終端で条件判定を行い、真であればループの最初に戻り、偽であればループから抜けるだけです。
while文
次はwhile文です。doとの違いは、条件判定をループの最後で行うか、最初で行うかです。それでは元になるコードから見てみましょう。
0 1 2 3 4 5 6 7 8 9 |
while (expr) { ... /* 処理1 */ break; ... /* 処理2 */ continue; ... /* 処理3 */ } |
まずは、上のコードを素直に書き直して見ます。
0 1 2 3 4 5 6 7 8 9 10 |
While: if (!expr) goto Endwhile; ... /* 処理1 */ goto Endwhile; /* break */ ... /* 処理2 */ goto While; /* continue */ ... /* 処理3 */ goto While; Endwhile: |
これでも構わないのですが、多くの場合、より効率を上げるために、コンパイラは次のようなコードを生成することが多いようです。
0 1 2 3 4 5 6 7 8 9 10 11 |
goto Next; While: ... /* 処理1 */ goto Endwhile; /* break */ ... /* 処理2 */ goto Next; /* continue */ ... /* 処理3 */ Next: if (expr) goto While; Endwhile: |
もちろん、こちらの方が常に効率がよいとは限らず、繰り返しの回数が非常に少ない場合や、CPUのアーキテクチャによっては最初の方が効率がよくなることもあり得ます。
for文
最後はfor文です。for文は、基本的にはwhile文と同じですが、ループの最初に評価される式と、ループが1回繰り返されるごとに評価される式がある点が異なります。それでは元になるコードです。
0 1 2 3 4 5 6 7 8 9 |
for (expr1; expr2; expr3) { ... /* 処理1 */ break; ... /* 処理2 */ continue; ... /* 処理3 */ } |
while文のときと同じように、まずは素直に書き直してみます。continue文を使った場合でも、expr3が評価される点に注意してください。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
expr1; For: if (!expr2) goto Endfor; ... /* 処理1 */ goto Endfor; /* break; */ ... /* 処理2 */ goto Next; /* continue */ ... /* 処理3 */ Next: expr3; goto For; Endfor: |
ループの最後で条件判定をする書き方は次のようになります。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
expr1; goto Next; For: ... /* 処理1 */ goto Endfor; /* break; */ ... /* 処理2 */ goto Next; /* continue */ ... /* 処理3 */ expr3; Next: if (expr2) goto For; Endfor: |
このように、繰り返し文もすべてif文とgoto文で書き直すことができます。最初にも書きましたが、実践的なプログラムでわざわざこんな書き方をすることはないでしょうが、一度は試しておくと、それぞれの制御構造の細かな振る舞いを完全に把握することができるようになります。
また、普段はあまり使う機会のないgoto文ですが、このように使い方を訓練しておけば、本当に必要なときに、適切にgoto文を使用するための助けとなることでしょう。