现在的位置: 首页 > 综合 > 正文

【编程思考】如何使用叛逆的goto ?

2017年12月12日 ⁄ 综合 ⁄ 共 2070字 ⁄ 字号 评论关闭

转载请注明本文地址:

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

抱歉!评论已关闭.