搜索
bottom↓
回复: 78

大家平时写代码,goto语句用的多吗?

  [复制链接]

出0入0汤圆

发表于 2016-10-8 13:38:51 | 显示全部楼层 |阅读模式

书上说尽量避免使用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);不知道大家都是怎么处理的。

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出280入168汤圆

发表于 2016-10-8 13:49:58 来自手机 | 显示全部楼层
不知道你啥意思?这个例子删掉goto效果不是一样吗?

出0入0汤圆

发表于 2016-10-8 13:51:36 | 显示全部楼层
linux bsp中用goto的特别多。

出0入90汤圆

发表于 2016-10-8 13:54:40 | 显示全部楼层
分两个函数写,goto 的地方换成 return + 参数

出0入8汤圆

发表于 2016-10-8 13:56:15 | 显示全部楼层
该用就用,就这么简单。

出20入70汤圆

发表于 2016-10-8 13:58:54 | 显示全部楼层
我都快忘掉这个关键字了,哈哈!

出0入42汤圆

发表于 2016-10-8 14:00:03 | 显示全部楼层
经常这么用:

  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. }
复制代码

出20入70汤圆

发表于 2016-10-8 14:01:24 | 显示全部楼层
特殊场合用的多,比如据说linux内核!
当然平时尽量不去用他,毕竟代码要给自己和别人维护的不是?

出0入42汤圆

发表于 2016-10-8 14:03:26 | 显示全部楼层
goto 不是禁语,只是应用场合需严格受限,最好仅用于快速退出函数或循环

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

出0入0汤圆

发表于 2016-10-8 14:07:31 | 显示全部楼层
本帖最后由 卢台长 于 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. }
复制代码

出0入0汤圆

发表于 2016-10-8 14:07:44 | 显示全部楼层
你这段代码用不用goto运行效果都是一样的。

出0入0汤圆

发表于 2016-10-8 14:17:12 来自手机 | 显示全部楼层
跳转在汇编里面是必须的,不明白c里面为什么不建议用

出50入8汤圆

发表于 2016-10-8 14:23:26 | 显示全部楼层
把goto out;全部去掉,不是一样的效果?

出0入0汤圆

发表于 2016-10-8 14:26:26 | 显示全部楼层
weichao4808335 发表于 2016-10-8 14:17
跳转在汇编里面是必须的,不明白c里面为什么不建议用

估计是涉及到堆栈保护指针的复位吧

出0入0汤圆

发表于 2016-10-8 14:46:36 | 显示全部楼层
weichao4808335 发表于 2016-10-8 14:17
跳转在汇编里面是必须的,不明白c里面为什么不建议用

工程规范。

出0入131汤圆

发表于 2016-10-8 14:50:00 | 显示全部楼层
从来不用goto,破坏结构,不在乎那点效率

出0入0汤圆

发表于 2016-10-8 14:52:15 | 显示全部楼层
一看就是从ASM转C的攻城狮

出100入101汤圆

发表于 2016-10-8 14:52:22 | 显示全部楼层
wshtyr 发表于 2016-10-8 14:03
goto 不是禁语,只是应用场合需严格受限,最好仅用于快速退出函数或循环

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

确如大牛所说,退出循环时,常用。

出0入169汤圆

发表于 2016-10-8 15:21:52 | 显示全部楼层
自从不常用VB了就没怎么用过

出0入0汤圆

发表于 2016-10-8 15:22:52 | 显示全部楼层
3个goto语句在这里完全多此一举,除掉逻辑仍然一样。

出0入8汤圆

发表于 2016-10-8 15:26:32 | 显示全部楼层
kebaojun305 发表于 2016-10-8 13:56
该用就用,就这么简单。

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

LZ,好好体会一下,不禁用,也不滥用。
如果,单单按照标题来回答的话,那么 goto 的出现概率是低的。

出10入10汤圆

发表于 2016-10-8 15:44:59 | 显示全部楼层
写程序时都忘记有goto关键字了

出0入0汤圆

发表于 2016-10-8 15:55:29 | 显示全部楼层
本帖最后由 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);

出0入93汤圆

发表于 2016-10-8 16:28:34 | 显示全部楼层
liufabing 发表于 2016-10-8 15:55
可以用do{} while(0);

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

10楼、23楼的请解释一下。

出0入0汤圆

发表于 2016-10-8 16:33:09 来自手机 | 显示全部楼层
不用goto,和10楼一样用的while

出0入0汤圆

发表于 2016-10-8 16:37:38 来自手机 | 显示全部楼层
goto就像拉屎不冲马桶一样,小心到时候内存不够用...... :)

出90入0汤圆

发表于 2016-10-8 16:37:46 | 显示全部楼层
好的编译器,
合适的等级,
你这种情况,用不用GOTO,得到的汇编语句,一样。

出0入0汤圆

发表于 2016-10-8 16:38:18 | 显示全部楼层
goto 主要是破坏了代码优化算法和执行预测

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

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

出0入0汤圆

发表于 2016-10-8 16:56:07 | 显示全部楼层
有用到,,,主要方便,,

出0入0汤圆

发表于 2016-10-8 17:09:16 | 显示全部楼层
经常用,linux的驱动中太多的goto了。很方便

出0入8汤圆

发表于 2016-10-8 17:31:56 | 显示全部楼层
takashiki 发表于 2016-10-8 16:28
写了十多年程序了,真心不知道do...while(0)除了宏定义需要外还有什么作用。
明明就一对花括号搞定的事情 ...

也坐等解答一下。

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

出0入31汤圆

发表于 2016-10-8 17:55:47 来自手机 | 显示全部楼层
错误处理用goto,其它情况一般不用

出0入75汤圆

发表于 2016-10-8 18:09:00 | 显示全部楼层
没有什么奇葩的逻辑需要用到goto。
continue, break就够用了。
LZ的程序,把goto去掉逻辑完全一样。

出0入0汤圆

发表于 2016-10-8 18:11:44 | 显示全部楼层
控制住范围,无所谓GOTO,想用就用
有时候在修改BUG的时候用GOTO很方便,不需要做太多调整,调整多了又是新BUG

一句话,看情况,书上的只能参考一切看实际情况

出0入46汤圆

发表于 2016-10-8 18:46:12 | 显示全部楼层

这个用法还是不错的。限定几种用法就行

出10入120汤圆

发表于 2016-10-8 18:50:32 来自手机 | 显示全部楼层
确实忘记了还有这条语句,仔细想想有些场合用起来应该还是很方便的,所以是可以用的,既然存在就是合理的。

出0入21汤圆

发表于 2016-10-8 18:57:16 | 显示全部楼层
表示从来没使用过.

出0入0汤圆

发表于 2016-10-8 19:24:51 | 显示全部楼层
最好不要随便用,否则死都不知道怎么死

出0入0汤圆

发表于 2016-10-8 21:19:30 | 显示全部楼层
break + return 就能解决问题
go to 是给菜鸟和高手用的。

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

出0入0汤圆

发表于 2016-10-8 21:39:09 | 显示全部楼层
goto out 用函数替代也是一样的。

出0入0汤圆

发表于 2016-10-8 22:57:54 | 显示全部楼层
goto在Linux驱动代码里用的很多,多层嵌套情况下,不用goto反倒使代码变得混乱

出0入0汤圆

发表于 2016-10-8 23:08:50 来自手机 | 显示全部楼层
个人觉得.太多循环条件嵌套的时候可以考虑使用.不必不用.不可滥用

出0入0汤圆

发表于 2016-10-8 23:24:38 | 显示全部楼层

kernel里面经常见这种写法

出0入0汤圆

发表于 2016-10-9 00:12:49 | 显示全部楼层
经常用 do{}while(0); 主流的C编译器一般都能优化这种结构,效率甚至代码和直接用GOTO没有差别。。

出0入93汤圆

发表于 2016-10-9 06:01:38 | 显示全部楼层
duanll 发表于 2016-10-9 00:12
经常用 do{}while(0); 主流的C编译器一般都能优化这种结构,效率甚至代码和直接用GOTO没有差别。。 ...


请回答我我在24楼的问题,为什么要用do{}while(0);而不是直接一对花括号?这样做有什么好处?10楼、23楼都不肯告诉我,你既然经常用,一定有您的理由,能否告诉我呢?
我觉得这根本就是脱裤子放屁多此一举,比goto更恶心。当然,宏定义中除外,那儿确实有用,然而,这样的场合比goto更局限。

出0入8汤圆

发表于 2016-10-9 08:57:10 来自手机 | 显示全部楼层
duanll 发表于 2016-10-9 00:12
经常用 do{}while(0); 主流的C编译器一般都能优化这种结构,效率甚至代码和直接用GOTO没有差别。。 ...

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

代码的首要客户是人,其次才是机器,
我更喜欢通俗易懂的代码。

出0入0汤圆

发表于 2016-10-9 09:00:38 | 显示全部楼层
takashiki 发表于 2016-10-8 16:28
写了十多年程序了,真心不知道do...while(0)除了宏定义需要外还有什么作用。
明明就一对花括号搞定的事情 ...

宏定义中其实也是可以用一对花括号代替的

出0入93汤圆

发表于 2016-10-9 09:06:46 | 显示全部楼层
myxiaonia 发表于 2016-10-9 09:00
宏定义中其实也是可以用一对花括号代替的

不可以的,必须照顾if的需求。

出0入0汤圆

发表于 2016-10-9 09:13:44 | 显示全部楼层
我一般很少用GOTO语句,大部分使用do{}while(0);来完成。

出0入8汤圆

发表于 2016-10-9 09:18:26 来自手机 | 显示全部楼层
myxiaonia 发表于 2016-10-9 09:00
宏定义中其实也是可以用一对花括号代替的

if macro else do something
要照顾这个 case,还是 do while 0 有用。

出0入0汤圆

发表于 2016-10-9 09:22:54 | 显示全部楼层
以前做一个液晶显示屏时用到了很多的goto,感觉非常好用

出0入0汤圆

发表于 2016-10-9 09:22:57 来自手机 | 显示全部楼层
chunjiu 发表于 2016-10-8 13:49
不知道你啥意思?这个例子删掉goto效果不是一样吗?

删掉就内存泄漏了

出0入0汤圆

发表于 2016-10-9 09:27:45 来自手机 | 显示全部楼层
zhuyihua001 发表于 2016-10-8 16:38
goto 主要是破坏了代码优化算法和执行预测

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

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

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

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

不过用goto大量乱跳显然不行。。。

出280入168汤圆

发表于 2016-10-9 09:51:44 | 显示全部楼层
xwkm 发表于 2016-10-9 09:22
删掉就内存泄漏了

除非你 if 里面有 return,否则哪里会产生泄露啊?

出0入0汤圆

发表于 2016-10-9 11:30:27 | 显示全部楼层
没用过,可能我们产品功能简单用不上

出0入0汤圆

发表于 2016-10-9 11:33:34 | 显示全部楼层
MISRA C中禁止使用Go to

出0入0汤圆

发表于 2016-10-9 11:34:01 | 显示全部楼层
MISRAC中禁止使用Go to

出0入0汤圆

发表于 2016-10-9 11:35:51 | 显示全部楼层
偶尔用,确实好用,但不依赖

出0入0汤圆

发表于 2016-10-9 11:54:04 | 显示全部楼层
很少用goto,我自己的代码里面基本不用Goto语句

出0入0汤圆

发表于 2016-10-9 12:07:11 | 显示全部楼层
security 发表于 2016-10-9 09:18
if macro else do something
要照顾这个 case,还是 do while 0 有用。

这种情况下 do while(0)可以作为判断条件么  怎么感觉有点怪异啊

出0入0汤圆

发表于 2016-10-9 12:11:40 来自手机 | 显示全部楼层
不要轻易否定goto,linux,window都用,难度那些程序员不如我们?

出0入0汤圆

发表于 2016-10-9 12:13:04 | 显示全部楼层
好用~~用得多

出0入0汤圆

发表于 2016-10-9 15:22:06 | 显示全部楼层
已经很多年没用了,差点忘了还有这语句

出0入8汤圆

发表于 2016-10-9 15:31:29 来自手机 | 显示全部楼层
myxiaonia 发表于 2016-10-9 12:07
这种情况下 do while(0)可以作为判断条件么  怎么感觉有点怪异啊

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

出0入0汤圆

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

通俗易懂和逻辑严密有时是冲突的,DO()WHILE(0);大部场合能平衡这种冲突。

出0入0汤圆

发表于 2016-10-9 15:43:53 | 显示全部楼层
本帖最后由 duanll 于 2016-10-9 15:45 编辑
takashiki 发表于 2016-10-9 06:01
请回答我我在24楼的问题,为什么要用do{}while(0);而不是直接一对花括号?这样做有什么好处?10楼、23楼 ...


请参照 48 楼

出0入0汤圆

发表于 2016-10-11 20:42:30 | 显示全部楼层
我记得曾几何时做过这样的,不知道现在有没有更好的方法。
内容就是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:

...
}

出0入0汤圆

发表于 2016-10-12 09:48:54 | 显示全部楼层

我感觉应该是很多人没有汇编那种跳转的概念,搞不好连那里出错都不知道

出0入93汤圆

发表于 2016-10-12 09:57:15 | 显示全部楼层
yiminglei_2 发表于 2016-10-11 20:42
我记得曾几何时做过这样的,不知道现在有没有更好的方法。
内容就是fun2返回0时,跳出三重循环。

跳出多重循环goto是最优雅的方式了,替代方案当然有,比如搞成子函数,比如搞成更变态的break+标号(最讨厌的Java特性,没有之一!)

出0入0汤圆

发表于 2016-10-12 11:51:47 | 显示全部楼层
感觉goto语句被教科书妖魔化了,分场合使用最佳,但是对于单片机一类的程序,把系统框架打好更重要。
分清楚应用场合是前后台程序、还是状态机、还是事件驱动、亦或是操作系统。
另外,LZ的程序,把goto去掉逻辑完全一样。。。

出0入0汤圆

发表于 2016-10-12 13:41:09 | 显示全部楼层
goto应该容易降低程序的可读性吧,毕竟有的程序需要给别人看,还要维护。

出0入0汤圆

发表于 2016-10-13 09:42:50 | 显示全部楼层
在kernel 的driver 层中,用goto 是很常见的,不要因为你不想用或者不会用而否定它。

出0入8汤圆

发表于 2016-10-13 10:14:56 | 显示全部楼层
可以看看此贴的衍生讨论:
那些膜拜do...while(0)的都什么心态
那里有更激烈的讨论。

出0入0汤圆

发表于 2016-10-13 10:46:39 | 显示全部楼层
很少用goto 语句了、、、、、

出0入0汤圆

发表于 2016-10-13 14:55:28 | 显示全部楼层
我自己没用过,goto只是慎用,不是禁用
如果用多了一个书写错误就不知跑哪去了
还有用多了程序跳来跳去,很难把思路理清,给别人维护的时候痛苦吧

出0入0汤圆

发表于 2016-10-13 17:01:44 | 显示全部楼层
基本上不会用

出0入0汤圆

发表于 2016-10-14 11:34:03 来自手机 | 显示全部楼层
用作出错处理,退出函数释放资源,没有更好的办法。用do{} while(0)的明显代码写的不够。你在while里面switch怎么办?有循环要退出怎么办?

出0入0汤圆

发表于 2016-10-14 13:09:41 | 显示全部楼层
xwkm 发表于 2016-10-9 09:22
删掉就内存泄漏了

我也想知道为什么会内存泄漏?

出0入8汤圆

发表于 2016-10-14 13:30:07 | 显示全部楼层
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 楼,那边给出了更详细的讨论帖链接。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 05:38

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表