为什么有些内核程序员使用goto而不是简单的while循环?
当我学习C时,老师终日告诉我:“不要使用goto,这是一个坏习惯,它很丑,很危险!” 等等。
那么为什么一些内核程序员使用goto
,比如在这个函数中 ,可以用一个简单的replace
while(condition) {}
要么
do {} while(condition);
我不明白这一点。 在某些情况下使用goto而不是while
/ do
会更好吗? 如果是这样,为什么?
在这个例子的情况下,我怀疑是将SMP支持改为最初以非SMP安全方式编写的代码。 goto again;
添加一个goto again;
path比重构function简单得多,侵入性也小一些。
我不能说我很喜欢这种风格,但是我也认为,为了避免意识形态的原因,要避免转向。 goto
用法的一个特例(不同于这个例子)是goto
只用于在一个函数中前进的地方,而不是后退。 这类用法从来不会导致goto
所产生的循环结构,而且它几乎总是最简单,最清晰的方式来实现所需的行为(通常是清理并返回错误)。
历史背景:我们应该记住,Dijkstra在1968年写了“ Goto Considered Harmful” ,当时很多程序员都用goto
代替了结构化编程 ( if
, while
, for
等等)。
44年过去了,在野外find这个goto
很less见。 结构化编程已经赢得了很久以前。
案例分析:
示例代码如下所示:
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
版本的时候,我认为这是一条直线,最后是一个“再试一次”的例子。
goto
版本在同一列上同时具有SETUP
和COMPUTE SOME VALUES
,强调大部分时间,控制stream都通过两者。 结构化版本将SETUP
和COMPUTE SOME VALUES
放在不同的列上,强调控制可以以不同的方式通过它们。
这里的问题是你想要在代码中强调什么样的? 您可以将其与goto
进行比较以进行error handling:
结构版本:
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;
生成的代码基本上是一样的,所以我们可以把它看作是一个排版问题,比如缩进。