C LANGUAGE TECHNOLOGY

【C言語】goto文が有用な3つの例外

悩んでいる人

C言語のgoto文って必要なの?

こういった悩みにお答えします.

本記事の信頼性

  • リアルタイムシステムの研究歴12年.
  • 東大教員の時に,英語でOS(Linuxカーネル)の授業.
  • 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
  • プログラミング歴15年以上,習得している言語: C/C++PythonSolidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
  • 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」GitHubにオープンソースとして公開
  • 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
  • 最近は自然言語処理AIイーサリアムに関する有益な情報発信に従事.
    • (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Bardなど)の記事を30本以上執筆.
    • (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を250本以上執筆.

こういった私から学べます.

C言語を独学で習得することは難しいです.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

goto文

goto文は,コード中の指定された場所(ラベル)に無条件にジャンプ(移動)する制御構造を持つ文です.

goto文のメリットは,自由度が高いコードを書けることです.

goto文の使い方は以下になります.

goto文のデメリットは,どこでもジャンプできることでコードが複雑になり,保守性が低くなることです.

例えば,アップル社の製品(iOS7,OSX,Safari)ではgoto文を利用したことによる脆弱性が発生しています.

なので,goto文は一般的には禁じ手と言われています.

そうすると,そもそもgoto文がなんであるのか疑問に思いますよね?

そこで,本記事ではC言語でgoto文が有用な3つの例外を紹介していきます.

また,C言語で開発された代表的なOS「Linux」におけるgoto文の利用例も取り上げます.

Linuxカーネルを学びたいあなたは,こちらからどうぞ.

C言語でgoto文が有用な3つの例外

C言語でgoto文が有用な3つの例外は以下になります.

  • 資源の獲得・解放を1:1対応にする場合
  • 多重構文から脱出する場合
  • 依存関係がある資源を獲得・解放する場合

資源の獲得・解放を1:1対応にする場合

資源の獲得・解放を1:1対応にする場合にgoto文を利用します.

C言語では,資源を獲得したら明示的に解放しなければなりません.

例えば,ファイルをfopen関数でオープンしたらfclose関数でクローズ,メモリをmalloc関数で獲得したらfree関数で解放します.

以下にメモリをmalloc関数で獲得する例を紹介します.

このコードはfunc関数でmalloc関数を呼び出してメモリを獲得していますが(14行目),free関数でメモリを解放していないのでメモリリークを起こしてしまいます.

なので,free関数を呼び出す正しいコードは以下になります.

このコードでは,malloc関数は14行目の1ヶ所で呼び出すのに対して,free関数は20行目と26行目の2ヶ所で呼び出さなくてはなりません.

よく読めば正しいコードだとわかりますが,パット見だと間違っているのでは?と疑わしいコードになってしまいます.

なので,malloc関数とfree関数の呼び出しを1:1対応にするために,goto文を利用して書き直した例が以下になります.

malloc関数は14行目の1ヶ所,free関数は26行目の1ヶ所でそれぞれ呼び出しています.

19行目のif文の返り値が0の場合,20行目で「goto end;」と書くことで25行目の「end:」にジャンプします.

このようにgoto文を利用することで,資源の獲得・解放を1:1対応にできます.

Linuxでは,kernel/sched/core.cファイルのwake_up_if_idle関数でgoto文が利用されています.

資源の獲得は6行目のrcu_read_lock関数,資源の解放は22行目のrcu_read_unlock関数で実行しています.

9行目の「goto out;」で,21行目の「out:」にジャンプします.

多重構文から脱出する場合

多重構文から脱出する場合にgoto文を利用します.

以下のコードでは,while文が13~24行目,switch文が16~23行目にあります.

scanf関数で数字を入力し,その数字がEXIT_NUMBERと等しい場合,18行目の「goto end;」で26行目の「end:」にジャンプします.

もし18行目をgoto文ではなくbreak文にする場合,switch文から脱出するだけになり,while文を再度実行してしまうことに注意して下さい.

※もちろんフラグを設定してif文を追加すれば多重構文から脱出できますが,冗長なコードになってしまいます.

Linuxでは,fs/ocfs2/super.cファイルのocfs2_parse_options関数でgoto文が利用されています.

while文が28~63行目,switch文が33~62行目にあります.

46行目で「goto bail;」で,79行目の「bail:」にジャンプします.

依存関係がある資源を獲得・解放する場合

依存関係がある資源を獲得・解放する場合にgoto文を利用します.

以下のコードでは,malloc関数とfree関数をそれぞれ3回呼び出しています.

goto文を利用することで,依存関係がある資源を獲得・解放するコードをスッキリ書けます.

※各々の資源の獲得・解放を1:1対応にしつつ多重構文を利用しないコードにもなっています.

Linuxでは,kernel/sched/core.cファイルのsched_tick_remote関数でgoto文が利用されています.

資源の獲得は22行目のrq_lock_irq関数,資源の解放は41行目のrq_unlock_irq関数で実行しています.

19行目のif文が偽の場合,20行目のgoto out_requeue;で42行目のrequeueラベルにジャンプします.

25行目のgoto out_unlock;で,40行目のout_unlock:にジャンプします.

つまり,19行目のtick_nohz_tick_stopped_cpu関数とrq_lock_irq関数の呼び出しが依存関係になっています.

まとめ

C言語でgoto文が有用な3つの例外を紹介しました.

  • 資源の獲得・解放を1:1対応にする場合
  • 多重構文から脱出する場合
  • 依存関係がある資源を獲得・解放する場合

これらの場合でgoto文を利用すると正しいコードをスッキリ書けますので,goto文の利用を検討してみてはいかがでしょうか.

goto文は以下の自作関数で利用していますので,実際のコードを知りたいあなたは,これらの記事を読みましょう!

goto文は同じ関数内でしかジャンプできませんが,他の関数にジャンプしたい場合はsetjmp/longjmp関数を利用します.

setjmp/longjmp関数の使い方を学びたいあなたはこちらからどうぞ.

C言語を独学で習得することは難しいです.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

-C LANGUAGE, TECHNOLOGY
-, , , , , , , , , ,