关于goto语句的一些个人思考~

来源:互联网 发布:易我数据恢复怎么用 编辑:程序博客网 时间:2024/05/16 10:51
        今天偶然看到了一篇讨论goto语句是否有害的文章,读后产生了写下一篇博文的冲动,以记录下自己对goto语句的看法。

        原文链接:http://www.drdobbs.com/architecture-and-design/is-goto-still-considered-harmful/240166595

        文章中首先以apple公司最新的代码bug说起,这个bug我最先看到是在2月份,链接是https://www.imperialviolet.org/2014/02/22/applebug.html。当时确实很是诧异,原来像apple这样的公司,也在使用goto语句。但这个错误并不是由于使用goto语句造成的,这仅仅是一个粗心的编辑错误。

        文中也提到了一个问题,为什么apple公司的程序员这么喜欢使用goto语句,在1970行中竟然有47个goto语句?并且在微软的一些例子程序中也经常把goto语句用来处理出错。我很赞同作者接下来提出的观点:“in C, there's little effective difference between goto and other, less taboo statements, like break inside a switch construct. In that spirit, careful use of goto can actually make code clearer. Another common reason given for using goto as a means of hand-optimization of code is less defensible.”确实,在C语言中,如果你清楚并且小心的使用goto语句,将会给你的工作带来很大的便利,使你的代码更加清晰。

        我尤记起在上家公司工作的时候,遇到过这样一个问题。当时有一段代码需要使用goto语句来处理,大致样式如下:

void func(void){       ...        goto lable;       ...        goto lable;       ... lable:      ...        if()       {            ...       }       ...       if()       {            ...       }       ...}

    这其实就是一段使用goto语句处理出错的代码。但是我的一位搞底层的上司认为这种格式是错误的,应该改成如下格式:

void func(void){       ...        if()       {             goto lable1;       }       ...        if()       {             goto lable2;       }       ... lable2:      ... lable1:      ...}

        诚然,这种用法才是linux系统中底层的标准用法。但是上面一种就错了吗?也不尽然。我在不少代码中见到过第一种用法,它也能比较清晰的对错误进行处理,并且很少出问题。因为它在做错误处理时,会首先对资源进行判断,然后才会释放。但是第二种方法,在使用时一定要注意顺序,哪个lable先处理要放前面,哪个后处理放后面,一定要做到清楚明白。不然很可能提前释放某些资源,并且不容易立即查找到错误(特别是多个进程共用资源时)。

        你以为这样就完了吗?不。当我把这份代码提交时,又遇到了一位做framework的上司,他在看到我的代码后,给出了ugly的评价。仅仅是因为我使用了goto语句!我当时很是气愤,当两个领导的意见不一致时,我们这些实际写代码的人,会很尴尬,并且无所适从。我当时的做法是将第二位上司的评价转给了第一位上司,并告诉第二位上司,第一位上司的观点,然后他们“打”了起来!就因为一个goto语句的使用,两位做了很多年开发的领导整整争吵了两天,并且各自请了很多朋友来给自己支持,仅仅是为了证明自己的观点是正确的。由此可以看出,一个没有接触过底层的工程师对goto语句的抵触有多深。

        最后这件事不了了之,谁也没有说服谁。

        说了这么多,我其实想要表达的观点还是上面的那句话:C语言中,可以小心谨慎的使用goto语句,前提是你真的会用!

        下面给出我认为的关于使用goto语句的原则:
  1. 使用goto语句只能goto到同一函数内,而不能从一个函数里goto到另外一个函数里。
  2. 使用goto语句在同一函数内进行goto时,goto的起点应是函数内一段小功能的结束处,goto的目的label处应是函数内另外一段小功能的开始处。
  3. 不能从一段复杂的执行状态中的位置goto到另外一个位置,比如,从多重嵌套的循环判断中跳出去就是不允许的。
  4. 应该避免向两个方向跳转。这样最容易导致"面条代码"。
0 0
原创粉丝点击