[c] カーネルプログラマの中には、単純なwhileループの代わりにgotoを使うのはなぜですか?


Answers

歴史的文脈: Dijkstraは、1968年に多くのプログラマーが構造化プログラミングifwhileforなど)の代わりにgotoを使用したとき、 Goto Considered Harmfulを書いたことを覚えておく必要があります。

44年後、野生でこのようなgoto使用を見つけることはまれです。 構造化プログラミングは、ずっと前に既に勝っています。

ケース分析:

サンプルコードは次のようになります。

    SETUP...
again:
    COMPUTE SOME VALUES...
    if (cmpxchg64(ptr, old_val, val) != old_val)
        goto again;

構造化バージョンは次のようになります。

SETUP...
do {
    COMPUTE SOME VALUES...
} while (cmpxchg64(ptr, old_val, val) != old_val);

構造化バージョンを見ると、すぐに「ループです」と思う。 私がgoto版を見ると、私はそれを "try again"ケースの最後の直線と考える。

gotoバージョンには、同じカラムにSETUPCOMPUTE SOME VALUES両方があります。これはほとんどの場合、制御フローが両方を通過することを強調しています。 構造化バージョンは、 SETUPCOMPUTE SOME VALUESを異なる列に置きます。これは、コントロールが異なる方法でそれらを通過する可能性があることを強調しています。

ここでの質問は、コードにどのような重点を置きたいのですか? エラー処理のためにgotoと比較することができます:

構造化バージョン:

if (do_something() != ERR) {
    if (do_something2() != ERR) {
        if (do_something3() != ERR) {
            if (do_something4() != ERR) {
                ...

後ろのバージョン:

if (do_something() == ERR)  // Straight line
    goto error;             // |
if (do_something2() == ERR) // |
    goto error;             // |
if (do_something3() == ERR) // |
    goto error;             // V
if (do_something4() == ERR) // emphasizes normal control flow
    goto error;

生成されるコードは基本的に同じなので、字下げのような印刷上の問題と考えることができます。

Question

私はCを学んだとき、教師は一日中教えてくれました。「gotoを使わないでください。それは悪い習慣です。醜いです、危険です! 等々。

それでなぜ、いくつかのカーネルプログラマはgoto使います。たとえば、この関数では単純なものに置き換えることができます

while(condition) {} 

または

do {} while(condition);

私はそれを理解できません。 while / do - whileの代わりにgotoを使う方が良いでしょうか? もしそうなら、なぜですか?






Links