我们经常编写一些具有多个出口点的函数(即return在C中).同时,当退出函数时,对于一些常规工作,例如资源清理,我们希望只实现一次,而不是在每个出口点实现它们.通常,我们可以通过使用如下所示的goto来实现我们的愿望:
void f()
{
...
...{..{... if(exit_cond) goto f_exit; }..}..
...
f_exit:
some general work such as cleanup
}
Run Code Online (Sandbox Code Playgroud)
我认为在这里使用goto是可以接受的,我知道很多人同意在这里使用goto.出于好奇,是否有任何优雅的方式可以在C中不使用goto而整齐地退出函数?
goto在几个SO讨论中已经对这个声明进行了长时间的讨论(见这个和那个),我当然不想重振那些激烈的辩论.
相反,我想专注于gotos 的单个用例并讨论它的价值和可能的替代方案.
请考虑以下代码片段,这在(至少我自己的)FSM中很常见:
while (state = next_state()) {
switch (state) {
case foo:
/* handle foo, and finally: */
if (error) goto cleanup;
break;
case bar:
/* handle bar, and finally: */
if (error) goto cleanup;
break;
/* ...other cases... */
}
}
return ok;
cleanup:
/* do some cleanup, i.e. free() local heap requests, adjust global state, and then: */
return error;
Run Code Online (Sandbox Code Playgroud)
在一个单独的函数中交换清理东西只是为了保存gotos似乎很尴尬.另一方面,我们已经被提出来谴责goto尽可能使用s.
我的问题:我的代码示例被认为是好风格吗?
如果没有,是否有可行的替代方案?
请坚持上述具体用法goto …
"goto"语句直接来自ASM或任何其他汇编语言.
这是一个链接:http://be2.php.net/manual/en/control-structures.goto.php
我想知道:这可以做些什么来使我的代码组织得更好?如何在大型项目中实现这一点,而不是搞砸它.由于goto允许你来回跳转,如果以错误的方式使用它,意外分配和无限循环等待发生.
有人能给我一个好用的例子吗?
编辑:好吧,我已经看到了一些回复,显然对使用"goto"语句存在广泛的共识而且它很糟糕.
所以我还在想:为什么PHP会把它添加到语言中呢.如果他们没有看到内容,他们就不会这样做......为什么呢?
EDIT2:看到这个问题引发了许多令人难过的goto声明,我去问我的父亲.他今年52岁,是一名工业工程师.
他曾多次告诉我他在他的日子里做了大量的编程,主要是在FORTRAN和COBOL.如今,他从事IT服务,服务器和网络管理等工作.
无论如何,他说了一些关于"回到我的日子......"的事情.
经过讨论后,他回到了goto声明,说即使在他作为学生的日子里,他们都知道这不是一个聪明的人想要使用它,但当时它们并没有好多少.尝试/捕获仍然是几年之后,错误处理几乎没有.
那么你做了什么检查你的程序?在最后添加几行,允许您打印输出以及检查代码所需的所有内容,然后放置行:"goto printing;"或类似内容,以开始打印数据.
通过这种方式,您逐步调试了代码.
他同意在现代编程世界中使用goto是没有用的.他认为合理的唯一用途是"紧急休息",用于极端调试和意外情况.有点像goto fatal_error;,并且代码的"fatal_error"部分会做一些事情来向您展示深入的结果.
但只是在创造某些东西的时候.成品不应该有goto语句.
LATE EDIT:关于PHP5.3/PHP6中"goto"的另一个讨论
在C中生成UTF-8 JSON的最佳方法是什么?我看过Jansson,但看起来非常笨重.是否有任何其他良好的低依赖库用于在C中创建和读取JSON对象/字符串?
我有一个问题可以简化到这个:
parameters: a, b
if (a > 5)
{
Print("Very well, a > 5");
if (b > 7)
Print("Even better, b > 7");
else
{
Print("I don't like your variables");
}
}
else
{
Print("I don't like your variables");
}
Run Code Online (Sandbox Code Playgroud)
我想只使用一个else而不是两个,因为它们是相同的代码.我想到的是创建一个额外的方法,它将返回组合的true`false`,但这是一个严重的矫枉过正.
另一种选择是a goto,但这会使代码更不易读和不安全.
有什么方法可以做到这一点,避免多次检查相同的条件并使其尽可能可读?
C11或C99的6.8.1节或C89的 3.6.1节似乎都表明default和case x(其中x一些是常量表达式)是标记语句的示例,identifier:适用于的旁边标签goto.
我知道,我可以简单地放置identifier:风格的标签直接跟随default:或case x:标签.这不是这个问题的关键所在.我更加好奇是否有任何实际的理由背后禁止这种行为.
如果可以在选择结构default:之外声明标签switch,那么我会理解,因为goto在switch选择结构的内部旨在瞄准的位置之间会存在一些冲突.然而,C11的部分6.4.1或C99或3.1.1 C89禁止使用default作为除了关键字之外的任何,并且6.8.1进一步限制了其使用,以switch仅结构(或generic结构在C11,这是无关紧要这里).
我也理解,如果多个(可能是嵌套的)switch结构,每个都带有default:(或case x:)标签引入了歧义,但是这些标签的范围似乎被限制在其最内部的周围switch结构中,并且引用其范围之外的任何标识符是显然是一个需要在编译时进行诊断的错误.
是否已在任何标准文件(例如理由)中讨论过这个问题?除了"因为它是"还是"因为规范是这样的"以外,对这种行为有什么解释吗?如果是这样,那是什么解释?
为什么gotojava中的关键字保留但未使用?
编辑:只是为了避免歧义再次重新解释这个问题,我理解java中不支持goto功能,并且理解它使代码难以阅读.但它不受支持,那么为什么要保留它.它至少可以用作变量名
这个问题的灵感来自如何将流程图转换为实现?它询问了从算法上消除goto代码语句的方法.本科学论文描述了一般问题的答案.
我已经根据Knuth的算法X 的高级草图实现了一些代码.计算机编程的艺术描述了带有限制前缀的词典排列的生成(参见本草案的第16页).
这是上述算法的相应流程图.
这可能是一个非常聪明且非常有效的算法,但代码的结构似乎很难遵循.我最终使用了良好的旧式goto实现:
//Algorithm X;
1:
initialize();
2:
enter_level(k);
3:
set(a[k],q);
if(test() == ok) {
if (k == n) {
visit();
goto 6;
}
goto 4;
}
goto 5;
4:
increase(k);
goto 2;
5:
increasev2(a[k]);
if (q != 0) {
goto 3;
}
6:
decrease(k);
if (k==0) {
goto 7;
} …Run Code Online (Sandbox Code Playgroud) 我在另一个论坛上发布了一个代码片段,寻求帮助,人们向我指出,使用GoTo语句是非常糟糕的编程习惯.我想知道:为什么不好?
GoTo在VB.NET中有哪些替代方法可以被认为是更好的做法?
请考虑以下用户必须输入其出生日期的片段.如果月/日/年无效或不切实际,我想循环回来并再次询问用户.(我正在使用if语句来检查整数的大小......如果有更好的方法可以做到这一点,我会很感激,如果你能告诉我那个:D)
retryday:
Console.WriteLine("Please enter the day you were born : ")
day = Console.ReadLine
If day > 31 Or day < 1 Then
Console.WriteLine("Please enter a valid day")
GoTo retryday
End If
Run Code Online (Sandbox Code Playgroud) 有没有办法为PHP定义全局标签(类似变量)goto,以便在函数声明中使用它.我想做以下事情:
function myFunction() {
if (condition) {
goto someLine;
}
}
someLine:
// ....
myFunction();
Run Code Online (Sandbox Code Playgroud)
当我使用这个代码时,它说
PHP Fatal error: 'goto' to undefined label "someLine"
Run Code Online (Sandbox Code Playgroud)
我知道不建议使用goto语句.但在我的情况下,我需要它.我知道也许总会有替代品goto,只是在我的情况下它会使代码更容易和可理解