この中でアセンブラでもjmp命令を使った事が無い者だけがgoto命令に石を投げなさい

 

 

こんにちは。ナガオカ(@boot_kt)です。

 

プログラミングで一番嫌われている命令って、、、

 

 

せーーーーのっ!!!!

 

 

 

 

 

 

ゴートゥーーー!

はい!、goto命令ですね

 

そんな可哀想なgoto命令についてアレコレ書いてみたいと思います

この記事のザックリした内容
◆対象読者

  • goto命令は諸悪の根源だ!と思って毛嫌いしている人
  • goto命令を好きで好きで使いまくっている人

 

◆解決できるかも知れないお悩み

  • goto命令の使い方のご提案

 

 

 

goto命令って悪いのか!?

先に言っておきますが、この記事はgoto命令を擁護します

  • こんな風にgoto命令を使ってみてはどう?
  • こんな風なgoto命令の使い方はダメだよね?

というような事を書きます

 

そもそも、goto命令悪人説がありますが、ホントにgoto命令が悪いの!???

そうなの???

 

違う違う、そうじゃ…そうじゃない!!!

 

お前の使い方が悪いんじゃーーーーーっ!!!!

goto命令は全く悪くないんじゃーーーーーーっ!!!

 

使い方の悪さを棚に上げてgoto命令ひとりに責任をなすりつけるなんてプログラマの風上にも置けない!!!

 

そもそも、なぜgoto命令が悪く言われているのか!?

goto命令が悪く言われるのはそれなりに理由があるのは理解してますよ

実際僕は仕事でgoto命令を使ったこと無いですし(笑)

まぁ、趣味のプログラムでも使ったことないかなwwwwwww

 

goto命令の何が悪いのか、振り返ってみましょう

と言っても、その理由は一つだけですけど・・・

いつでもどこでも(と言っても同じ関数内だけのはず)飛んで行ける!

このコードを見ると、ちょっとややこしいですよね
※もっとややこしく書きたかったけど、これ以上goto命令使うとワケ分からんようになるので止めました(笑)

#include 

void subFunction(void);

main()
{
    int hoge = 10;
    int fuga = 20;
    int hege;
    int i;

    hege = hoge + fuga;

    goto JUMP1;
    hege = 100;


JUMP1:
    printf("JUMP1 %d \n", hege);

    goto JUMP2;
    hege = 200;
    printf("---- \n");


JUMP2:
    for(i=0; i<100; i++) {
        printf("JUMP2 %d \n", hege);

        goto JUMP3;
    }
    hege = 300;
    printf("---- \n");


JUMP3:
    printf("JUMP3 %d \n", hege);

    return ;
}

void subFunction(void)
{
JUMP3:
    printf("aaaa");

    return;
}
>gototest.exe
JUMP1 30
JUMP2 30
JUMP3 30

ところどころでhegeに値を入れてるんですけど、結局goto命令のせいで値がセットされないんですよね
printf("---- \n");も実行されないし
for命令なんて、100回処理するのかなと思いきや1回しか処理しないし、

 

 

そうなんです、gotoを多用すると分かりづらいソースコードになっちゃうんです
今回のサンプルは処理の流れが下に下に行くようにしているので読めなくもないですが、
上に戻ったり、下に行ったり、上に戻ったり、下に行ったり、・・・・
みたいなことをすると、、、もうそのソースコードを読むのは不可能に近くなります。

そら、嫌われますわwww

 

でもgoto命令の代わりにこんなことやっていませんか?

ちょっとC言語以外ではよく分かりませんが、goto命令を使いたいけど使えない時にこんな書き方しませんか?

Javaとかだと...
オブジェクト指向系であればfinally的なものを使いますよね
#include 

main()
{
    int i;

    for (i=0; i<100; i++) {

        printf("count %d \n", i);

        if(i > 3) {
            break;
        }
    }

    printf("end \n");

    return;
}
>goto2.exe
count 0
count 1
count 2
count 3
count 4
end

 

#include 

main()
{
    int i = 0;

    while(1) {

        printf("count %d \n", i);

        if(i > 3) {
            break;
        }

        i++;
    }

    printf("end \n");

    return;
}
>goto3.exe
count 0
count 1
count 2
count 3
count 4
end

 

#include 

main()
{
    int  i         = 0;
    char error     = 0;
    char something = 1;

    do {


        /* 何かの処理...... */


        if(something) {
            printf("something \n");

            /* エラーフラグON */
            error = 1;
        }


        /* 何かの処理...... */


        if(error) {
            printf("error \n");

            /* do を脱出 */
            break;
        }


        /* 何かの処理...... */

        printf("while-end \n");
    } while(0);

    printf("end \n");

    return;
}
>goto4.exe
something
error
end

 

別にこういう書き方が悪いとは思いません
が、やってることはgoto命令と大差無いですよね

なので、goto命令だけを悪者にするのはちょっと可愛そうです

 

それでもワシはgoto命令を擁護するでっっっっ!

まぁでも、前章の書き方は飛び先が固定されるしそれ以外の使い方が無いんですよね
goto命令のように飛び先自由ってこともできないのでgoto命令と全く同じというわけではないですね

finally的な命令が無い場合、この書き方は結構便利だったりします
僕も仕事書いたことありますし

 

で、提案ですけど、goto命令もfinally的に使ってみてはどうでしょう?

こんな感じ↓

#include 
#include 

#include 

main()
{
    int   i         = 0;
    char  error     = 1;
    char* pc1       = NULL;
    char* pc2       = NULL;


    /* メモリ確保1 */
    pc1 = (char*)malloc(10);
    if(pc1 == NULL) {
        printf("メモリ1確保失敗 \n");
        goto JUMP_CLEANUP;
    }
    printf("メモリ1確保成功 \n");


    /* 何かの処理...... */


    /* メモリ確保2 */
    pc2 = (char*)malloc(10);
    if(pc2 == NULL) {
        printf("メモリ2確保失敗 \n");
        goto JUMP_CLEANUP;
    }
    printf("メモリ2確保成功 \n");


    /* 何かの処理...... */


    if(error) {
        printf("error \n");

        goto JUMP_CLEANUP;
    }


    /* 何かの処理...... */


    printf("end \n");


JUMP_CLEANUP:
    if(pc1 != NULL) {
        printf("メモリ1解放 \n");
        free(pc1);
    }
    if(pc2 != NULL) {
        printf("メモリ2解放 \n");
        free(pc2);
    }

    return;
}
>goto5.exe
メモリ1確保成功
メモリ2確保成功
error
メモリ1解放
メモリ2解放

 

あくまでも後始末のみに使うんです
コーディング規約でそう決めて、コードレビューでチェックすればいいのでは?

goto命令の飛び先ラベルも固定にしてしまえば、grep(←全てのファイルを一括で検索すること)でチェックできるし

 

広告




 

さいごに、

goto命令に関しては以前から思うところがあり、使うことはしないですけど可哀想だなとずっと思っていました

別にgoto命令自体は悪くなくて、人間の使い方が悪いだけなのに....

まぁ、だからと言って使うことは推奨しませんし、僕も今後も使わないと思いますwww

でも、goto命令自体は悪くない!!
悪いのは人間だ!!

それを言いたいだけです...

あと、ハンガリアン記法も本当は悪くないんですよ
誤解されたまま広まってしまい、ハンガリアン記法も悪いヤツという風潮になってしまいました

nb

みなさん、プログラミングの命令や記法にもっと愛情を注いであげてください!!!

 

 

アセンブラ「ん? goto使おうがどうしようが、jmp命令使いまくりだぞ!?」
※gccなら、gcc -S hoge.cgcc -S -g hoge.cでコンパイルしてみてね

 


 

プログラミング のレッスンに興味がある方、レッスン内容を聞いてみたい方、なんなりとお問い合わせください。
無料体験レッスンもありますのでお気軽にどうぞ!!!

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

ABOUTこの記事をかいた人

Windows/Mac/Linuxを使う現役システムエンジニア&プログラマ。オープン系・組み込み系・制御系・Webシステム系と幅広い案件に携わる。C言語やC#やJava等数多くのコンパイラ言語を経験したが、少し飽きてきたので、最近はRubyやPython、WordPressなどのWeb系を修得中。初心者向けのプログラミング教室も運営中。オンライン・対面・出張等でプログラミングをレッスンします。