转载请注明本文地址:
http://blog.csdn.net/elezeor/article/details/11707283
记得看过不少本编程书,
提及goto这个语法时,
每本几乎都是简单地介绍一下用法,
然后注明一句:
尽可能的不要使用这个语法,
因为它极有可能破坏程序的完整性以及逻辑性。
诚然,
编程整个思维过程都要考虑严密,
每一步都要尽可能地处于编程者的控制之下,
然而goto这个"指哪打哪"的语法显然具有太强的自由性了,
对于大部分程序员来说,
其危险程度之高,
甚至不亚于背后忽然飘过一扫地大爷的一句"栈溢出了…"。
然而,
我不喜欢被束缚思想,
同时,我也认为一个事物的存在必然具有相应的价值。
于是,
经过思考及尝试及搜索,
终于发现goto在以下几种情况是可以一用的。
【跳出多个for循环】
for ... for ... if(canBreakOut()) goto final; final:
这种情况大家最容易理解,
但其实像这样一下子跳出多个循环的办法也有不少,
比如说你可以将这多个for循环写在一个函数里,
然后在想要退出的时候return一下也可以。
不过这样的话,
goto的优势也显而易见了。
【代替do{}while(0)】
在讲这个之前,
看来有必要先简要概述一下do{}while(0)的使用:
这个语法?被称之为防御式编程,
最大的优点有两个,
一个是可以是现在C++的宏定义中,
同时解决将多个命令写在一个宏中以及宏尾部的分号问题。
具体请看这里。
而第二个优点,
就是我们可以用它来代替多个if内的数个重复命令语句:
比如说这样的代码:
if(occurFirstException()) { handleExceptionOnFirstStep(); handleExceptionOnSecondStep(); } else if(occurSecondException()) { handleExceptionOnFirstStep(); handleExceptionOnSecondStep(); } //...
我们就可以使用do{}while(0)来简化:
void detectException() { do { if(occurFirstException()) break; //... if(occurSecondException()) break; //... }while(0); handleExceptionOnFirstStep(); handleExceptionOnSecondStep(); }
那么这与goto有什么关系呢?
答案很简单,
因为goto也具有类似的用法:
void detectException() { if (occurFirstException()) { goto OUT; } if (occurSecondException()) { goto OUT; } //... OUT: unlock(thingy); return; }
而且相比之下goto还具有一个隐藏的好处:
在C#等语言中实现do{}while(false)的用法时,
会有警告提示具有不可执行代码,
但是如果改成goto,
则不会出现警告。
【实现逻辑清晰的有条件循环】
为什么在循环前面加上诸多限定词呢,
那是因为,
在大部分情况下(99.999%?),
这种循环都可以被while或是for(;;)替代,
然而,
产生的问题就是:
语义变得更为模糊。
代码如下:
restart: if (system_call() == -1) { if (errno == EINTR) goto restart; // handle real errors }
当然,
你也可以使用while来写作用相同的代码:
while (system_call() == -1) { if (errno != EINTR) { // handle real errors break; } }
但如果稍微敏感一些的读者,
会一眼看到这两者之间的区别:
goto是以条件优先,从而实现循环。
while却让人误解为先循环,然后再去判断条件。
怎样?是否有些强词夺理?
确实如此,
因为我们从编程开始就习惯了避开goto,
转而使用其他语法代替,
久而久之,
原本一些看似歪曲的念头却慢慢地被大家所接受,
成为了心目中"正直“ 的标杆。
而原本为此而生的语法,
却因其强大的副作用而被束之高阁。
笔者在此并不争论孰是孰非,
就像面向对象编程也好,面向函数编程也好,面向过程编程也好,
在合适的地方选择合适的工具,
这样才是编程最为理想的境界。
结尾:
goto语句本身的用法其实并不仅限于如此,
大部分的程序员都很聪明,
毕竟,聪明的猴子都有自己剥香蕉的方式,
因此肯定还有各种千奇百怪的用法夹杂在行行代码之中,
比如说Donald E. Knuth的这篇论文:
http://cs.sjsu.edu/~mak/CS185C/KnuthStructuredProgrammingGoTo.pdf
最后是本文部分内容链接:
http://stackoverflow.com/questions/245742/examples-of-good-gotos-in-c-or-c
2013.9.15 By Elezor