Goto文

goto文とは



プログラミング言語における`goto`文は、プログラムの実行フローを特定の場所へ無条件に移動させるための制御文です。この「特定の場所」は、通常ラベルと呼ばれるもので指定されます。`goto`文は、機械語における無条件分岐命令と密接な関係があり、アセンブリ言語のラベルを高級言語に持ち込んだものと考えることができます。

概要



`goto`文単独では機能せず、必ずジャンプ先のラベルを必要とします。条件分岐と組み合わせることで、ループやコードブロックのスキップといった機能を実現できます。しかし、`goto`文だけでは、それがループのためなのか、単なるジャンプなのかが不明確になりやすく、コードの可読性を損なう原因となることがあります。

例えば、`if`文や`while`文で簡単に記述できる処理を`goto`文で記述すると、コードの意図が分かりにくくなります。そのため、多くの場合は`goto`文の使用は避けるべきとされています。しかし、深くネストしたループから脱出するような場合には、`goto`文がコードをより明確に記述できることもあります。特にC言語においては、`goto`文を全面的に排除するべきではないという意見もあります。

資源の確保と解放が必須なケースなど、プログラムの入口と出口を厳密に対応させる必要がある場合、`goto`文だけでなく、途中returnなどの他の手法も制限されることがあります。このような制限は、`goto`文自体の問題とは区別して考えるべきです。

また、ジョークとして「`comefrom`文」という、ジャンプ先からジャンプ元に移動するような概念も提案されています。この概念は、プログラム理論の研究対象にもなっています。

構文



`goto`文は、ラベル付きの文と組み合わせて使用されます。以下は、C言語での使用例です。

c
goto clear;
// ...
clear:
// 処理


この例では、`goto clear;`によって`clear:`というラベルの場所へジャンプし、そこから処理が続行されます。

批判



構造化プログラミングの観点から、`goto`文は安易に使用すべきではないとされています。これは、`goto`文が自由度が高すぎるため、プログラムの構造を複雑にし、デバッグメンテナンスを困難にするからです。`goto`文の使用は、バグの発生や可読性の低下につながりやすいと指摘されています。

しかし、多重ループや複雑なエラー処理など、`goto`文を使った方がプログラムがすっきりする場合もあります。そのため、熟練したプログラマーは、状況に応じて`goto`文を使い分けるべきだと考えられています。

エラー処理や例外処理、RAIIといった仕組みが充実している言語では、`goto`文が必要になるケースは少ないです。特にオブジェクト指向言語では、`goto`文が言語仕様から除外されていることもあります。一方、PHPのように、後から`goto`文が追加された例もあります。

BASICのような言語では、`goto`文が必須であり、`goto`文なしでは分岐やループを記述できない場合があります。しかし、拡張されたBASICでは、`goto`文がほとんど不要になっているものもあります。

`goto`文を安易に使うと、コードの可読性が著しく低下し、スパゲティコードと呼ばれる状態になりがちです。

goto文論争



1968年、計算機科学者のダイクストラは「Go To Statement Considered Harmful(`goto`文は有害である)」という論文を発表し、大きな論争を引き起こしました。ダイクストラの主張は、プログラムの静的な構造と実行時の動的な構造を一致させることが重要であり、`goto`文はそれを妨げるというものでした。

ダイクストラは、`goto`文を無条件に許すと、プログラムの進行状況を示す簡潔な指標を得ることが難しくなると主張しました。その結果、上位水準のプログラミング言語においては、`goto`文を廃止すべきであると結論付けました。ただし、ダイクストラは、構造化プログラミングに関する別の論文では、`goto`文についてほとんど言及していません。

ダイクストラは、「3つの基本構造」(連接、選択、繰り返し)についても、「これらがすべてのニーズを満たすわけではない」としており、`goto`文の有無に固執するのは不毛であると述べています。

3つの基本構造



「goto文有害説」は、しばしば構造化定理と結びつけて語られます。構造化定理とは、任意のフローチャートで表現できる計算可能な関数は、「連接」、「選択」、「繰り返し」という3つの基本構造で表現できるというものです。この定理は、計算可能な関数を表現する様々な方法(チューリングマシンラムダ計算など)と同列に扱われます。しかし、構造化定理は、プログラムが人間に分かりやすいかどうかについては触れていません。

「gotoのないプログラム」に書き換えると、実際にはコードが複雑になり、可読性が損なわれる場合もあります。クヌースは、構造化定理が示すのは、非構造化プログラミングであると指摘しています。

goto擁護派



`goto`文を使わずに3つの基本構造で代替すると、実行速度やメモリ使用量において性能が劣化する場合があるため、`goto`文を擁護する意見も存在します。また、必要な機能をプログラミング言語で直接表現できない場合、`goto`文を使って実装を工夫するべきだという主張もあります。クヌースは、再帰呼び出しをループに書き換えた結果、`goto`文を使った方が良い例もあると述べています。

gotoの現在



現在では、C言語を除く多くの主流言語で`goto`文はほとんど見られなくなりました。代わりに、`break`文、`continue`文、例外処理などが使われ、単純な制御構造を補っています。また、クロージャやコードブロックといった強力な制御機構を持つ言語では、`goto`文を使う必要性はさらに低くなっています。

ただし、D言語やC#、PHPのように、後から`goto`文をサポートした言語も存在します。

その他の話題



`goto`文に関する論争は、プログラミング技法の体系化を試みるプログラミング工学という学問の誕生にも影響を与えました。「Go To Statement Considered Harmful」という論文の題名は、他の分野でも模倣され、「〜は有害である」という表現が広まりました。

ダイクストラの著書は、難解で誤解を招きやすいことで知られており、それを憂いたデビッド・グリースは、ダイクストラ流のプログラミングを体系化した書籍を執筆しました。

gotoとバグ



`goto`文を使っていれば避けられたバグ



1990年に発生したAT&Tの長距離電話網の停止は、`break`文の脱出先を間違えたことが原因でした。このバグは、適切なラベルと`goto`文を使っていれば回避できた可能性があります。

`goto`文の誤った記述によるバグ



アップルのSSL/TLS実装で発見された脆弱性「goto fail」は、`goto`文の誤った記述が原因でした。このバグでは、本来実行されるべき署名検証処理がスキップされていました。ただし、これは`goto`文自体の問題というよりは、C言語の構文とインデントのミスリードが原因であるという見方もできます。

まとめ



`goto`文は、プログラムの実行フローを直接制御できる強力な命令ですが、その自由度の高さから、プログラムの可読性を損ない、バグの原因となることもあります。そのため、多くの場合は`goto`文の使用は避けるべきですが、状況によっては、コードをより明確にできる場合もあります。`goto`文を使用する際は、その影響を十分に理解し、慎重に判断する必要があります。

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。