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)
生成的代码基本相同,因此我们可以将其视为排版问题,如缩进.
R..*_*R.. 30
在这个例子中,我怀疑它是关于将SMP支持改进为最初以非SMP安全方式编写的代码.添加goto again;路径比重构功能要简单得多,侵入性也小.
我不能说我喜欢这种风格,但我也认为goto出于意识形态的原因而避免这种做法是错误的.一个特殊的goto使用情况(与此示例不同)goto是仅用于在函数中向前移动,而不是向后移动.这类用法从来不会产生循环结构goto,并且它几乎总是最简单,最清晰的方式来实现所需的行为(通常是清理并返回错误).