amobbs.com 阿莫电子技术论坛

标题: 大家平时写代码,goto语句用的多吗? [打印本页]

作者: wq_601840968    时间: 2016-10-8 13:38
标题: 大家平时写代码,goto语句用的多吗?

书上说尽量避免使用goto,但是有些情况下用goto会很方便,
如下代码:

int  fun()
{
        int result = 0;
        char * buffer = malloc(100);

        if(buffer == NULL)
        {
                return -1;
        }

       if(XXX)
        {
                if(XXX)
                {
                        result = 1;
                        goto out;
                }
                else
                {
                        result = 2;
                        goto out;
                }               
        }
        else
        {
                result = 3;
                goto out;
        }

out:
        free(buffer);
        return result ;

}

否则需要多处 写free(buffer);不知道大家都是怎么处理的。
作者: chunjiu    时间: 2016-10-8 13:49
不知道你啥意思?这个例子删掉goto效果不是一样吗?
作者: yinjinzhong    时间: 2016-10-8 13:51
linux bsp中用goto的特别多。
作者: aammoo    时间: 2016-10-8 13:54
分两个函数写,goto 的地方换成 return + 参数
作者: kebaojun305    时间: 2016-10-8 13:56
该用就用,就这么简单。
作者: techbaby    时间: 2016-10-8 13:58
我都快忘掉这个关键字了,哈哈!
作者: wshtyr    时间: 2016-10-8 14:00
经常这么用:

  1. fun(...)
  2. {
  3.   FILE * fp1 = NULL;
  4.   FILE * fp2 = NULL;
  5.   void * hdr = NULL;
  6.   fp1 = fopen("file1","rb");
  7.   fp2 = fopen("file2","wb");
  8.   hdr = ModuleCreate(...);

  9.   if(fp1 == NULL || fp2 == NULL || hdr == NULL) goto exit;
  10.   ...



  11. exit:
  12.   if(fp1 != NULL) fclose(fp1);
  13.   if(fp2 != NULL) fclose(fp2);
  14.   if(hdr != NULL) ModuleDestroy(hdr);
  15. }
复制代码

作者: techbaby    时间: 2016-10-8 14:01
特殊场合用的多,比如据说linux内核!
当然平时尽量不去用他,毕竟代码要给自己和别人维护的不是?
作者: wshtyr    时间: 2016-10-8 14:03
goto 不是禁语,只是应用场合需严格受限,最好仅用于快速退出函数或循环

当然,艺高人胆大的可以用在switch-case里
作者: 卢台长    时间: 2016-10-8 14:07
本帖最后由 卢台长 于 2016-10-9 11:20 编辑

楼主改为这样试试(do{...}while(0)):不要使用goto普遍是受教科书影响
  1. int  fun()
  2. {
  3.     int result = 0;
  4.     char * buffer = malloc(100);
  5.         
  6.     do {
  7.         if(buffer == NULL)
  8.         {
  9.             result = -1;
  10.             break;
  11.         }

  12.        if(XXX)
  13.         {
  14.             if(XXX)
  15.             {
  16.                 result = 1;
  17.                 break;
  18.             }
  19.             else
  20.             {
  21.                 result = 2;
  22.                 break;
  23.             }               
  24.         }
  25.         else
  26.         {
  27.             result = 3;
  28.             break;
  29.         }
  30.     } while (false);

  31.     free(buffer);
  32.     return result ;

  33. }
复制代码

作者: yu_studio    时间: 2016-10-8 14:07
你这段代码用不用goto运行效果都是一样的。
作者: weichao4808335    时间: 2016-10-8 14:17
跳转在汇编里面是必须的,不明白c里面为什么不建议用
作者: airbox    时间: 2016-10-8 14:23
把goto out;全部去掉,不是一样的效果?
作者: hgh1013    时间: 2016-10-8 14:26
weichao4808335 发表于 2016-10-8 14:17
跳转在汇编里面是必须的,不明白c里面为什么不建议用

估计是涉及到堆栈保护指针的复位吧
作者: stdio    时间: 2016-10-8 14:46
weichao4808335 发表于 2016-10-8 14:17
跳转在汇编里面是必须的,不明白c里面为什么不建议用

工程规范。
作者: asj1989    时间: 2016-10-8 14:50
从来不用goto,破坏结构,不在乎那点效率
作者: daicp    时间: 2016-10-8 14:52
一看就是从ASM转C的攻城狮
作者: fengyunyu    时间: 2016-10-8 14:52
wshtyr 发表于 2016-10-8 14:03
goto 不是禁语,只是应用场合需严格受限,最好仅用于快速退出函数或循环

当然,艺高人胆大的可以用在switc ...

确如大牛所说,退出循环时,常用。
作者: d__xin    时间: 2016-10-8 15:21
自从不常用VB了就没怎么用过
作者: GoingDown    时间: 2016-10-8 15:22
3个goto语句在这里完全多此一举,除掉逻辑仍然一样。
作者: security    时间: 2016-10-8 15:26
kebaojun305 发表于 2016-10-8 13:56
该用就用,就这么简单。

该用就用,就这么简单。+1

LZ,好好体会一下,不禁用,也不滥用。
如果,单单按照标题来回答的话,那么 goto 的出现概率是低的。
作者: szxszx    时间: 2016-10-8 15:44
写程序时都忘记有goto关键字了
作者: liufabing    时间: 2016-10-8 15:55
本帖最后由 liufabing 于 2016-10-8 16:00 编辑

可以用do{} while(0);

  1. int  fun()
  2. {
  3.     int result = 0;
  4.     char * buffer = malloc(100);

  5.     do
  6.     {
  7.         if(buffer == NULL)
  8.         {
  9.             result -1;   
  10.         }

  11.        if(XXX)
  12.         {
  13.             if(XXX)
  14.             {
  15.                 result = 1;
  16.             }
  17.             else
  18.             {
  19.                 result = 2;
  20.             }               
  21.         }
  22.         else
  23.         {
  24.                 result = 3;
  25.         }
  26.     }
  27.     while(0);
  28.     if (result != -1)
  29.     (
  30.         free(buffer);
  31.         return result ;
  32.     )
  33. }
复制代码


------------------------编辑----------------------------
应该用10楼的,我这少了break.
不过都是do{} while(0);
作者: takashiki    时间: 2016-10-8 16:28
liufabing 发表于 2016-10-8 15:55
可以用do{} while(0);

写了十多年程序了,真心不知道do...while(0)除了宏定义需要外还有什么作用。
明明就一对花括号搞定的事情

10楼、23楼的请解释一下。
作者: q457344370    时间: 2016-10-8 16:33
不用goto,和10楼一样用的while
作者: wiser803    时间: 2016-10-8 16:37
goto就像拉屎不冲马桶一样,小心到时候内存不够用...... :)
作者: hzpyl    时间: 2016-10-8 16:37
好的编译器,
合适的等级,
你这种情况,用不用GOTO,得到的汇编语句,一样。
作者: zhuyihua001    时间: 2016-10-8 16:38
goto 主要是破坏了代码优化算法和执行预测

所以一般通用程序不建议用goto破坏编译器优化

程序员自己不怕累,用goto,自己脑力就优化咯


作者: litop    时间: 2016-10-8 16:56
有用到,,,主要方便,,
作者: avr-arm    时间: 2016-10-8 17:09
经常用,linux的驱动中太多的goto了。很方便
作者: security    时间: 2016-10-8 17:31
takashiki 发表于 2016-10-8 16:28
写了十多年程序了,真心不知道do...while(0)除了宏定义需要外还有什么作用。
明明就一对花括号搞定的事情 ...

也坐等解答一下。

对于 do while (0) 替换 goto 的做法,个人而言,我是不推荐这种做法的,
刚接触这技巧的时候,也实践过,不过现在基本被打入冷宫了,
年纪大了,更喜欢简单直观的代码。

作者: zchong    时间: 2016-10-8 17:55
错误处理用goto,其它情况一般不用
作者: Doding    时间: 2016-10-8 18:09
没有什么奇葩的逻辑需要用到goto。
continue, break就够用了。
LZ的程序,把goto去掉逻辑完全一样。
作者: passage110    时间: 2016-10-8 18:11
控制住范围,无所谓GOTO,想用就用
有时候在修改BUG的时候用GOTO很方便,不需要做太多调整,调整多了又是新BUG

一句话,看情况,书上的只能参考一切看实际情况
作者: jasonzhu8888    时间: 2016-10-8 18:46
wshtyr 发表于 2016-10-8 14:00
经常这么用:

这个用法还是不错的。限定几种用法就行
作者: makesoft    时间: 2016-10-8 18:50
确实忘记了还有这条语句,仔细想想有些场合用起来应该还是很方便的,所以是可以用的,既然存在就是合理的。
作者: 117433525    时间: 2016-10-8 18:57
表示从来没使用过.
作者: p4s5j6    时间: 2016-10-8 19:24
最好不要随便用,否则死都不知道怎么死
作者: not_at_all    时间: 2016-10-8 21:19
break + return 就能解决问题
go to 是给菜鸟和高手用的。

---------------------------------
当然,艺高人胆大的可以用在switch-case里----------no zuo no die!


作者: handshake    时间: 2016-10-8 21:39
goto out 用函数替代也是一样的。
作者: 伍师傅32    时间: 2016-10-8 22:57
goto在Linux驱动代码里用的很多,多层嵌套情况下,不用goto反倒使代码变得混乱
作者: bg6agf    时间: 2016-10-8 23:08
个人觉得.太多循环条件嵌套的时候可以考虑使用.不必不用.不可滥用
作者: tabing    时间: 2016-10-8 23:24
wshtyr 发表于 2016-10-8 14:00
经常这么用:

kernel里面经常见这种写法
作者: duanll    时间: 2016-10-9 00:12
经常用 do{}while(0); 主流的C编译器一般都能优化这种结构,效率甚至代码和直接用GOTO没有差别。。
作者: takashiki    时间: 2016-10-9 06:01
duanll 发表于 2016-10-9 00:12
经常用 do{}while(0); 主流的C编译器一般都能优化这种结构,效率甚至代码和直接用GOTO没有差别。。 ...


请回答我我在24楼的问题,为什么要用do{}while(0);而不是直接一对花括号?这样做有什么好处?10楼、23楼都不肯告诉我,你既然经常用,一定有您的理由,能否告诉我呢?
我觉得这根本就是脱裤子放屁多此一举,比goto更恶心。当然,宏定义中除外,那儿确实有用,然而,这样的场合比goto更局限。
作者: security    时间: 2016-10-9 08:57
duanll 发表于 2016-10-9 00:12
经常用 do{}while(0); 主流的C编译器一般都能优化这种结构,效率甚至代码和直接用GOTO没有差别。。 ...

问题的关键不在优化效率的差异上,而在于你容易理解,别人是否也容易理解呢?
没接触过的人,或许会认为写法好怪,我就曾被人指出这一点,要知道,那个人的技术水平,在当时甩我几百条街。

代码的首要客户是人,其次才是机器,
我更喜欢通俗易懂的代码。
作者: myxiaonia    时间: 2016-10-9 09:00
takashiki 发表于 2016-10-8 16:28
写了十多年程序了,真心不知道do...while(0)除了宏定义需要外还有什么作用。
明明就一对花括号搞定的事情 ...

宏定义中其实也是可以用一对花括号代替的
作者: takashiki    时间: 2016-10-9 09:06
myxiaonia 发表于 2016-10-9 09:00
宏定义中其实也是可以用一对花括号代替的

不可以的,必须照顾if的需求。
作者: lo-lo25    时间: 2016-10-9 09:13
我一般很少用GOTO语句,大部分使用do{}while(0);来完成。
作者: security    时间: 2016-10-9 09:18
myxiaonia 发表于 2016-10-9 09:00
宏定义中其实也是可以用一对花括号代替的

if macro else do something
要照顾这个 case,还是 do while 0 有用。
作者: circle_head    时间: 2016-10-9 09:22
以前做一个液晶显示屏时用到了很多的goto,感觉非常好用
作者: xwkm    时间: 2016-10-9 09:22
chunjiu 发表于 2016-10-8 13:49
不知道你啥意思?这个例子删掉goto效果不是一样吗?

删掉就内存泄漏了
作者: xwkm    时间: 2016-10-9 09:27
zhuyihua001 发表于 2016-10-8 16:38
goto 主要是破坏了代码优化算法和执行预测

所以一般通用程序不建议用goto破坏编译器优化

现代CPU的分支预测能力和现代编译器的优化能力早解决了这个问题。

就算你用do while(0)输出汇编也一样,该预测失败还是预测失败。

错误处理不用goto很容易出现屁股没擦赶紧的问题,比如内存泄漏或者死锁。而且goto指向很清晰是函数尾部的扫尾程序。不会破坏程序结构。

不过用goto大量乱跳显然不行。。。
作者: chunjiu    时间: 2016-10-9 09:51
xwkm 发表于 2016-10-9 09:22
删掉就内存泄漏了

除非你 if 里面有 return,否则哪里会产生泄露啊?
作者: llj1007    时间: 2016-10-9 11:30
没用过,可能我们产品功能简单用不上
作者: jiamingz    时间: 2016-10-9 11:33
MISRA C中禁止使用Go to
作者: jiamingz    时间: 2016-10-9 11:34
MISRAC中禁止使用Go to
作者: EngKing    时间: 2016-10-9 11:35
偶尔用,确实好用,但不依赖
作者: sywh    时间: 2016-10-9 11:54
很少用goto,我自己的代码里面基本不用Goto语句
作者: myxiaonia    时间: 2016-10-9 12:07
security 发表于 2016-10-9 09:18
if macro else do something
要照顾这个 case,还是 do while 0 有用。

这种情况下 do while(0)可以作为判断条件么  怎么感觉有点怪异啊
作者: Excellence    时间: 2016-10-9 12:11
不要轻易否定goto,linux,window都用,难度那些程序员不如我们?
作者: linux-0405209    时间: 2016-10-9 12:13
好用~~用得多
作者: firewind    时间: 2016-10-9 15:22
已经很多年没用了,差点忘了还有这语句
作者: security    时间: 2016-10-9 15:31
myxiaonia 发表于 2016-10-9 12:07
这种情况下 do while(0)可以作为判断条件么  怎么感觉有点怪异啊

不好意思,那边我少打了个 if 的表达式。

作者: duanll    时间: 2016-10-9 15:42
security 发表于 2016-10-9 08:57
问题的关键不在优化效率的差异上,而在于你容易理解,别人是否也容易理解呢?
没接触过的人,或许会认为 ...

通俗易懂和逻辑严密有时是冲突的,DO()WHILE(0);大部场合能平衡这种冲突。
作者: duanll    时间: 2016-10-9 15:43
本帖最后由 duanll 于 2016-10-9 15:45 编辑
takashiki 发表于 2016-10-9 06:01
请回答我我在24楼的问题,为什么要用do{}while(0);而不是直接一对花括号?这样做有什么好处?10楼、23楼 ...


请参照 48 楼
作者: yiminglei_2    时间: 2016-10-11 20:42
我记得曾几何时做过这样的,不知道现在有没有更好的方法。
内容就是fun2返回0时,跳出三重循环。

void fun1(void)
{
U32 i,j,k,a1,a2,b1,b2,c1,c2;
...

for(i=a1; i<a2; i++)
for(j=b1; j<b2; j++)
for(k=c1; k<c2; k++)
if(fun2(i, j, k) == 0)
goto out;

out:

...
}
作者: weichao4808335    时间: 2016-10-12 09:48
stdio 发表于 2016-10-8 14:46
工程规范。

我感觉应该是很多人没有汇编那种跳转的概念,搞不好连那里出错都不知道
作者: takashiki    时间: 2016-10-12 09:57
yiminglei_2 发表于 2016-10-11 20:42
我记得曾几何时做过这样的,不知道现在有没有更好的方法。
内容就是fun2返回0时,跳出三重循环。

跳出多重循环goto是最优雅的方式了,替代方案当然有,比如搞成子函数,比如搞成更变态的break+标号(最讨厌的Java特性,没有之一!)
作者: yanshanbao    时间: 2016-10-12 11:51
感觉goto语句被教科书妖魔化了,分场合使用最佳,但是对于单片机一类的程序,把系统框架打好更重要。
分清楚应用场合是前后台程序、还是状态机、还是事件驱动、亦或是操作系统。
另外,LZ的程序,把goto去掉逻辑完全一样。。。
作者: atomshuai_2.0    时间: 2016-10-12 13:41
goto应该容易降低程序的可读性吧,毕竟有的程序需要给别人看,还要维护。
作者: ALUMEI    时间: 2016-10-13 09:42
在kernel 的driver 层中,用goto 是很常见的,不要因为你不想用或者不会用而否定它。
作者: security    时间: 2016-10-13 10:14
可以看看此贴的衍生讨论:
那些膜拜do...while(0)的都什么心态
那里有更激烈的讨论。
作者: karaxiaoyu    时间: 2016-10-13 10:46
很少用goto 语句了、、、、、
作者: lw32    时间: 2016-10-13 14:55
我自己没用过,goto只是慎用,不是禁用
如果用多了一个书写错误就不知跑哪去了
还有用多了程序跳来跳去,很难把思路理清,给别人维护的时候痛苦吧

作者: zcf287    时间: 2016-10-13 17:01
基本上不会用
作者: bart    时间: 2016-10-14 11:34
用作出错处理,退出函数释放资源,没有更好的办法。用do{} while(0)的明显代码写的不够。你在while里面switch怎么办?有循环要退出怎么办?
作者: peecehood    时间: 2016-10-14 13:09
xwkm 发表于 2016-10-9 09:22
删掉就内存泄漏了

我也想知道为什么会内存泄漏?
作者: security    时间: 2016-10-14 13:30
bart 发表于 2016-10-14 11:34
用作出错处理,退出函数释放资源,没有更好的办法。用do{} while(0)的明显代码写的不够。你在while里面swit ...

我想,你错了,
如果 do {} while (0) 里面,再嵌套 switch while 的话,break 还是只影响 switch while,并不会影响到外层的 do {} while (0) 。

关于 do {} while (0) 的利弊,参考 73 楼,那边给出了更详细的讨论帖链接。




欢迎光临 amobbs.com 阿莫电子技术论坛 (https://www.amobbs.com/) Powered by Discuz! X3.4