为什么有些内核程序员使用goto而不是简单的while循环?

mus*_*tze 51 c linux loops goto linux-kernel

当我学习C语言时,老师终日告诉我:"不要使用goto,这是一个坏习惯,它很丑,很危险!" 等等.

那么,为什么一些内核程序员会使用goto,例如在这个函数中,它可以用一个简单的替换

while(condition) {} 
Run Code Online (Sandbox Code Playgroud)

要么

do {} while(condition);
Run Code Online (Sandbox Code Playgroud)

我无法理解.在某些情况下使用goto而不是while/ do- 更好while吗?如果是这样,为什么?

Die*_*Epp 58

历史背景:我们应该记住,Dijkstra算法写后藤是有害于1968年,当时很多程序员使用goto作为替代结构化程序设计(if,while,for等).

这是44年之后,goto在野外很难找到这种用途.很久以前,结构化编程已经赢得了胜利.

案例分析:

示例代码如下所示:

    SETUP...
again:
    COMPUTE SOME VALUES...
    if (cmpxchg64(ptr, old_val, val) != old_val)
        goto again;
Run Code Online (Sandbox Code Playgroud)

结构化版本如下所示:

SETUP...
do {
    COMPUTE SOME VALUES...
} while (cmpxchg64(ptr, old_val, val) != old_val);
Run Code Online (Sandbox Code Playgroud)

当我看结构化版本时,我立刻想到,"这是一个循环".当我看到这个goto版本时,我认为它是一条直线,最后会有"再试一次"的情况.

goto版本具有两个SETUP并且COMPUTE SOME VALUES在同一列上,强调大多数时间,控制流都通过两者.结构化版本看跌期权SETUP,并COMPUTE SOME VALUES在不同的栏目,其中强调控制可以通过它们不同.

这里的问题是你想在代码中加入什么样的重点?您可以将其与goto错误处理进行比较:

结构化版本:

if (do_something() != ERR) {
    if (do_something2() != ERR) {
        if (do_something3() != ERR) {
            if (do_something4() != ERR) {
                ...
Run Code Online (Sandbox Code Playgroud)

转到版本:

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;
Run Code Online (Sandbox Code Playgroud)

生成的代码基本相同,因此我们可以将其视为排版问题,如缩进.

  • [内核程序员同意](http://programmers.stackexchange.com/a/154980/27881).如果你有ERR1,ERR2 ...... ERRN,那么你可以'转到clean_err1;`/ etc并反转这些更改,就好像它是堆栈一样. (7认同)
  • +1表示goto如何强调预期的控制流程. (3认同)

R..*_*R.. 30

在这个例子中,我怀疑它是关于将SMP支持改进为最初以非SMP安全方式编写的代码.添加goto again;路径比重构功能要简单得多,侵入性也小.

我不能说我喜欢这种风格,但我也认为goto出于意识形态的原因而避免这种做法是错误的.一个特殊的goto使用情况(与此示例不同)goto是仅用于在函数中向前移动,而不是向后移动.这类用法从来不会产生循环结构goto,并且它几乎总是最简单,最清晰的方式来实现所需的行为(通常是清理并返回错误).

  • 对于当前的编译器来说通常都是如此; 在内部将`while`解构为条件`goto`之后,它们优化了代码流图. (3认同)