C 中使用 goto 会被打吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
codechaser
V2EX    C

C 中使用 goto 会被打吗?

  •  
  •   codechaser 2018-11-28 19:21:30 +08:00 12151 次点击
    这是一个创建于 2580 天前的主题,其中的信息可能已经有所发展或是发生改变。

    突发奇想,C 中的 goto 和我以前学的单片机里的汇编跳转好像,感觉很强大啊。假如大型项目里使用 goto 会被打吗?

    < href="/tag/Goto" class="tag">
  • Goto
  • 单片机
  • 汇编
  • 突发奇想
    102 条回复    2018-11-30 18:08:56 +08:00
    1  2  
    boris1993
        1
    boris1993  
       2018-11-28 19:22:43 +08:00 via Android   5
    买好保险,定好床位

    大胆的去试吧少年!
    shylockhg
        2
    shylockhg  
       2018-11-28 19:25:12 +08:00
    不会
    lihongjie0209
        3
    lihongjie0209  
       2018-11-28 19:25:32 +08:00
    如果就你一个人的开发的话, 不会
    liuxu
        4
    liuxu  
       2018-11-28 19:26:26 +08:00   6
    不会,linux 内核源码中使用了很多 goto

    https://github.com/torvalds/linux/search?q=goto&unscoped_q=goto
    kljsandjb
        5
    kljsandjb  
       2018-11-28 19:26:43 +08:00 via iPhone
    看情况而定吧
    Kaiv2
        6
    Kaiv2  
       2018-11-28 19:26:53 +8:00 via Android
    试试看能不能使用 break 替换
    whoisghost
        7
    whoisghost  
       2018-11-28 19:27:02 +08:00
    有时候,没有 goto,代码反而更难读。
    lanyusea
        8
    lanyusea  
       2018-11-28 19:27:07 +08:00
    看编程规范的要求了,有的公司或者组织要求严格一些。

    我平时会用到,刚搜了一下 Linux 的源码里面也有 goto 关键字
    IllBeBack
        9
    IllBeBack  
       2018-11-28 19:28:29 +08:00
    有 goto 为什么不用,除非不知道怎么用,没有另说。
    wanderpoet
        10
    wanderpoet  
       2018-11-28 19:30:27 +08:00 via iPhone
    说了很多遍了 goto 完全被妖魔化了 正常使用 提高多重循环终止效率 有什么问题
    huobazi
        11
    huobazi  
       2018-11-28 19:32:19 +08:00
    能漂亮的解决问题就好,有时候 goto 能使代码易读易用
    across
        12
    across  
       2018-11-28 19:32:42 +08:00
    大型项目不需要别人打你,自己维护一个月 goto 就疯了
    scnace
        13
    scnace  
       2018-11-28 19:34:26 +08:00 via Android
    go 里面用会被打吗?
    scnace
        14
    scnace  
       2018-11-28 19:35:20 +08:00 via Android
    很多在 for{} 里面的时候会用 goto 跳出来 会让代码简洁很多
    bigmouthhaile
        15
    bigmouthhaile  
       2018-11-28 19:36:55 +08:00 via Android
    以前写 linux 内核驱动的时候,用了好多 goto
    Cbdy
        16
    Cbdy  
       2018-11-28 19:41:57 +08:00   2
    异常处理可以用 goto、longjump,而且其实用 goto 反而好,因为程序已经 crash 了

    Dijkstra 的意思是,不要用 goto 做流程分支控制
    pkookp8
        17
    pkookp8  
       2018-11-28 19:45:36 +08:00 via Android
    第一眼看成了 c 内嵌 go 语言,反应是没人会的东西,能打死的先打死
    仔细一看是 goto
    为什么不能用,代码逻辑清晰 goto 又怎么会让逻辑复杂化?
    内核,bootloader 用 goto 的地方多了去了,怎么没重构
    有些地方不用 goto 反而加入了非常多的冗余代码
    glacer
        18
    glacer  
       2018-11-28 19:48:47 +08:00
    用 goto 来跳出多重循环非常简洁易懂
    shijingshijing
        19
    shijingshijing  
       2018-11-28 19:50:12 +08:00
    三层 for 循环,要做到高效跳出最外层的循环,请给我一个比 goto 更高效更易懂更优雅的方法。
    ryd994
        20
    ryd994  
       2018-11-28 19:51:51 +08:00 via Android
    @liuxu 这和 Linux 里的使用不是一回事
    Linux 里只允许 goto cleanup
    楼主想的是用 goto 到处乱飞
    乱飞是一定会被打死的,都不用别人,过两个月你自己就想打死自己。
    linxu
        21
    linxu  
       2018-11-28 19:52:34 +08:00 via Android
    据说 goto 在 linux 内核中,也用到了。。。
    codechaser
        22
    codechaser  
    OP
       2018-11-28 20:04:55 +08:00
    @liuxu 请教一下这样在线怎么在一个仓库里搜索关键字啊?我在 github 里输`goto repo:torvalds/linux`搜不到你这些
    r6Vm94FFk9u3W6XI
        23
    r6Vm94FFk9u3W6XI  
       2018-11-28 20:14:21 +08:00
    只要逻辑清晰,我觉得没什么不能用的
    读 redis 源码的时候,里面也有用到 goto
    iceheart
        24
    iceheart  
       2018-11-28 20:20:38 +08:00 via Android
    等你维护别人的代码的时候你就不觉得 goto 好了。
    gamexg
        25
    gamexg  
       2018-11-28 20:30:22 +08:00
    @scnace #13 标准库里面见过不少 goto exit。多层循环我一般是 break label 跳出
    easylee
        26
    easylee  
       2018-11-28 20:32:14 +08:00 via Android
    IDE 中使用 goto 的话,日后维护代码并无问题。

    如果单纯用 vim 或者记事本,那就另当别论。
    justou
        27
    justou  
       2018-11-28 20:32:57 +08:00
    见得最多的 goto 用法还是异常处理跟资源释放
    yuriko
        28
    yuriko  
       2018-11-28 20:33:58 +08:00
    事实上是,如果问这个问题的人,一般建议是不要用,因为理解不够瞎用容易死
    如果对 goto 的使用场景有了充分理解了,自然就不会再纠结这个问题
    Halry
        29
    Halry  
       2018-11-28 20:36:07 +08:00 via Android
    我之前也像别人说的不用 goto
    结果 goto 真的好好用啊哈哈哈
    JamesR
        30
    JamesR  
       2018-11-28 20:51:48 +08:00
    我认为跳转处离得近可以用 goto,其他就别用了。
    MrStark
        31
    MrStark  
       2018-11-28 20:53:03 +08:00
    当年我就是用 goto 而惨被同事捅死的 [滑稽]
    chiu
        32
    chiu  
       2018-11-28 21:00:21 +08:00 via Android
    小型使用不会
    nealwx
        33
    nealwx  
       2018-11-28 21:02:47 +08:00
    我一开始是抱着 goto 不要的想法的,后来发现 goto 用了之后反而少了很多冗余的代码
    orangeade
        34
    orangeade  
       2018-11-28 21:14:14 +08:00 via Android
    cpython 里也有 goto, 这得看项目类型和团队规范了
    ecee
        35
    ecee  
       2018-11-28 21:15:00 +08:00 via Android
    c 还好吧,同事 c# 用 goto 怎么办_
    rebackhua
        36
    rebackhua  
       2018-11-28 21:27:13 +08:00
    goto 很好用,出错处理,多重循环之类的
    BBge
        37
    BBge  
       2018-11-28 21:28:58 +08:00 via Android
    看到 goto 就想起给一个加拿大老师当 C++助教的时候 有一个学生问老师能不能用 goto 老师一脸鄙夷的表情
    ghhardy
        38
    ghhardy  
       2018-11-28 21:33:04 +08:00 via Android
    Kelly 不是说了么,有时在深层嵌套的循环中测试查找一个值,一旦找到则跳出循环的时候,用 goto 能提高效率。但他同时也建议,一般尽量不要用。
    Doodlister
        39
    Doodlister  
       2018-11-28 22:29:31 +08:00 via Android   1
    尽可能少用前向 GO TO
    避免使用后向 GO TO
    Android2MCU
        40
    Android2MCU  
       2018-11-28 22:37:32 +08:00 via iPhone
    Android 系统源码里面也一堆 goto 呢,够大型嘛( ̄ ̄)


    不过确实基本上都是出错处理之类的
    chainmon
        41
    chainmon  
       2018-11-28 22:45:30 +08:00 via Android
    竟然存在 goto 为什么不能用?
    fbcskpebfr
        42
    fbcskpebfr  
       2018-11-28 23:01:45 +08:00 via Android
    最近因为课程要求在看 Linux2.4.*的 kernel。许多函数,例如 fork,就用了 goto,应对复杂的情况
    t6attack
        43
    t6attack  
       2018-11-28 23:02:54 +08:00   1
    体制内计算机系教育,最开始学编程时(大学 C 语言基础课),老师就教导大家,不要使用 goto,因为它会破坏代码的结构性。
    然后,打开 linux 源码,到处都是 goto。
    catror
        44
    catror  
       2018-11-28 23:07:13 +08:00 via Android
    别用的太飘逸就好了
    VDimos
        45
    VDimos  
       2018-11-28 23:09:47 +08:00 via Android
    众所周知,c/c 艹里面是没有 goto 关键字的
    xupefei
        46
    xupefei  
       2018-11-28 23:11:04 +08:00
    goto 性能超高,但是需要手动维护堆栈和寄存器。
    如果上下文非常清晰(比如明显不会造成内存泄漏),那么用 goto 没啥不好的。
    ryd994
        47
    ryd994  
       2018-11-29 04:07:04 +08:00 via Android
    @t6attack
    @ruimz
    @Android2MCU

    Linux 里使用 goto 是有明确规则的
    https://www.kernel.org/doc/html/v4.10/process/coding-style.html#centralized-exiting-of-functions
    楼主是想把 goto 当 JMP 指令用到处乱飞
    乱飞 100%被打死,不出两个月自己就想打死自己
    ryd994
        48
    ryd994  
       2018-11-29 04:11:13 +08:00 via Android
    据我所知,Linux 里用 goto 但不是 cleanup 的只有一处,就是 CPU scheduler。这里可以用,是因为 CPU scheduler 逻辑很复杂,但又必须保证高性能。可读性已经无所谓了,反正本来就没几个人看得懂 /敢修改。
    Android2MCU
        49
    Android2MCU  
       2018-11-29 07:08:56 +08:00 via iPhone
    @ryd994 这样子的话,真是被打死都不多
    Akiyu
        50
    Akiyu  
       2018-11-29 08:07:08 +08:00
    慎用 goto
    bobuick
        51
    bobuick  
       2018-11-29 08:27:50 +08:00
    goto 适用的时候代码更可读。 写 golang 也偶尔会用,有时候没有 goto 可能就拆下写成递归才行
    xxgirl2
        52
    xxgirl2  
       2018-11-29 08:28:54 +08:00
    一个函数里一堆 open、alloc 随便炸一个要保证不泄露用 goto 就方便。其他情况尽量避免。
    多重循环、递归展开之类的大神级玩法用好 goto 会让代码更清晰。

    把 C 当汇编写迟早会自杀的。
    gesaint
        53
    gesaint  
       2018-11-29 08:53:22 +08:00 via iPhone
    当然不会,总有适合它的地方
    BOYPT
        54
    BOYPT  
       2018-11-29 08:56:32 +08:00
    C 里面做异常处理时候 goto 是很合适的呀
    看 nginx 源码里面的 goto 多舒服。
    haon
        55
    haon  
       2018-11-29 09:00:17 +08:00
    我校 c 语言考试明确规定不能用 goto
    turi
        56
    turi  
       2018-11-29 09:16:50 +08:00
    我从来没用过 goto
    aihidao
        57
    aihidao  
       2018-11-29 09:21:40 +08:00 via Android
    @VDimos ?额?

    我前几个月前接到过有 goto 的 c++项目。
    NB40B938mff85mtq
        58
    NB40B938mff85mtq  
       2018-11-29 09:23:17 +08:00
    我肯定是往死打~~
    Vegetable
        59
    Vegetable  
       2018-11-29 09:32:07 +08:00
    合理使用...当然了,编写合理的代码对一些人来说是很难的,所以只能编写不合理但是更不容易出错的代码.
    无论是 linux 还是 nginx,团队平均 coding 能力都自不必说,当然能驾驭好手里的工具.
    如果对你司实力水平有信心,当然可以用更跳脱的工具.
    liuxu
        60
    liuxu  
       2018-11-29 09:36:04 +08:00
    @ryd994

    大家都流传“ goto 有害,禁止 goto ”,代码里任何时候都不要用 goto,所以我举了一个反例

    写汇编也不会 goto/jmp 满天飞,都是跳到 ret 前恢复栈指针的代码,或者和 break 同义
    besto
        61
    besto  
       2018-11-29 09:49:31 +08:00
    @across
    @VDimos 读读 kernel code, goto 就是满天飞.


    这个问题应该分情况讨论. 做 cleanup, 时推荐使用; 跳出多重循环时, 可以使用, 但最好别用; goto 当作循环任何时候都应该禁止, 尤其在 goto 到循环里的情况(当然这种情况有特例)
    yulitian888
        62
    yulitian888  
       2018-11-29 10:11:45 +08:00
    不准用 goto,就跟驾校里“发动机 2000 转换挡”一样,是半吊子教练忽悠学员的说辞。
    如果 goto 真的那么邪恶,后面发展起来的高级语言像 java,c#什么的,还留着丫干嘛呢?
    robot777
        63
    robot777  
       2018-11-29 10:20:09 +08:00
    个人喜欢 goto 逻辑复杂实时比较简洁,不过一个函数里面也就用一次,怕把自己绕进去
    absente
        64
    absente  
       2018-11-29 10:30:46 +08:00
    同理可证,代码里用中文并不会被打
    swananan
        65
    swananan  
       2018-11-29 10:32:42 +08:00
    goto 不要往回跳
    xwander
        66
    xwander  
       2018-11-29 10:50:45 +08:00
    @swananan 赞同。

    if
    goto exit;



    exit:
    free(A);
    free(B);
    free(C);

    可以统一地写一个退出操作,用 goto 跳到后面
    td width="10" valign="top">
    bwangel
        67
    bwangel  
       2018-11-29 10:50:50 +08:00   1
    goto 的原则是可以向下跳,但是不能向上跳。函数中处理错误,用 goto 就 像 Python 中的 try: ... Except e: ... 读起来也是很清晰的。
    SPACELAN
        68
    SPACELAN  
       2018-11-29 11:15:14 +08:00
    用来跳过 block 块或者做退出处理还是蛮好用的

    用 goto 做循环的确会被打
    deadEgg
        69
    deadEgg  
       2018-11-29 11:50:43 +08:00
    形成 goto 方法的思维定势就行,写完后都能理解 goto 写法就行。

    开发规范+1
    realpg
        70
    realpg  
    PRO
       2018-11-29 12:07:29 +08:00   3
    goto 是个好东西
    前提是你用得好 用的合理 不要弄乱套

    之所以禁止 goto 主要是用不好的人 就会写出难以维护的代码 考虑到得失相关 所以很多地方规范是不让用 goto


    个人经验 goto 一般可以用于以下场合

    1. 短距离跳转 上下 5 行内 目的标签跟 goto 一一对应 不存在一对多或者多对一

    2. 向下跳出代码块

    3. 类似高级语言异常处理的用法 结束本方法之前的收尾工作

    4. 特定小循环(一般也匹配 1 )
    wdv2ly
        71
    wdv2ly  
       2018-11-29 12:11:02 +08:00
    千万别,goto 就像毒品,一旦用了就停不下来了 doge
    liuxu
        72
    liuxu  
       2018-11-29 12:18:44 +08:00
    @codechaser

    其实已经搜出来了,你需要点击“ Code ”,或者“ goto repo:torvalds/linux extension:c ”
    kkhaike
        73
    kkhaike  
       2018-11-29 13:21:00 +08:00
    我感觉 goto 只有一种情况 c 下的错误处理
    passerbytiny
        74
    passerbytiny  
       2018-11-29 13:42:10 +08:00
    @yulitian888 #61 不好意思,Java 里面 goto 是“不可用关键字”,你要敢用,就是编译错误。
    syntaxsugar
        75
    syntaxsugar  
       2018-11-29 13:46:59 +08:00 via Android
    grewer
        76
    grewer  
       2018-11-29 13:50:53 +08:00
    您好,会的
    akakcolin
        77
    akakcolin  
       2018-11-29 13:56:19 +08:00
    没事的,只用 goto 来做错误处理
    比如这样:if(SUCCESS != (ret = mfunc(ctx, &ct))) goto err;
    其他时候也不需要
    zwh2698
        78
    zwh2698  
       2018-11-29 13:59:28 +08:00 via Android
    请看驱动内核,大量的 goto 存在,只是理由要充分
    huadi
        79
    huadi  
       2018-11-29 13:59:54 +08:00
    @yulitian888 你说应该多少转换挡?
    codechaser
        80
    codechaser  
    OP
       2018-11-29 14:16:09 +08:00
    @zwh2698 最近刚开始认真学习 C,还不敢看这么高端的东西,也不知道从哪儿看,不能好高骛远。。。
    codechaser
        81
    codechaser  
    OP
       2018-11-29 14:16:50 +08:00
    @liuxu 哦,看到了,谢谢。
    yulitian888
        82
    yulitian888  
       2018-11-29 14:17:19 +08:00
    @passerbytiny java 疏忽了,不严谨。这里 java 耍了一个小把戏,把一部分 goto 的功能换成了 break 关键字去用了。
    语法为 break labelName;


    @huadi 换挡时机和车型有关。比如标致、雪铁龙普遍偏高,即所谓的“法系高转速发动机”,可以自己去试试看 2000 换挡是什么感觉。
    stackexplode
        83
    stackexplode  
       2018-11-29 14:20:17 +08:00
    错误处理 Goto 也可以用 do while(0),goto 必要性太小了
    jeffersonpig
        84
    jeffersonpig  
       2018-11-29 14:21:11 +08:00
    用得好就不会。
    Mohanson
        85
    Mohanson  
       2018-11-29 14:50:06 +08:00
    在 go 里学会 goto 后, 代码简洁了不少
    passerbytiny
        86
    passerbytiny  
       2018-11-29 14:52:10 +08:00
    @yulitian888 #81 这不是小把戏,这就是明确的告诉你,别想用 goto。java 就两个保留关键字 const、goto,const 是真正的预留关键字,将来可能回用,而 goto 能被保留的原因就是不想让你用。
    passerbytiny
        87
    passerbytiny  
       2018-11-29 14:56:15 +08:00
    @yulitian888 #81
    C#的 goto,是有严格的限制条件的:
    https://www.cnblogs.com/erikxu/archive/2006/11/18/564229.html
    shm7
        88
    shm7  
       2018-11-29 15:01:18 +08:00
    我觉得操作系统和普通程序不太一样,不复杂的程序,一般不用 goto 也行。用 goto 也是要考虑可读性的呀。
    FrankFang128
      nbsp; 89
    FrankFang128  
       2018-11-29 15:03:54 +08:00
    goto FAIL
    Raymon111111
        90
    Raymon111111  
       2018-11-29 15:06:55 +08:00
    业务代码最好别用
    yulitian888
        91
    yulitian888  
       2018-11-29 15:14:32 +08:00
    @passerbytiny 没 get 到我说的意思?
    goto 不是关键字,我承认,疏忽了。但是 c 语言中 goto 代表的“无条件跳转”行为在 java 中是明确存在的,仅仅只是换了别的关键字来实现而已。
    以上,你的回复毫无关系。除非你能证明,java 并不提供 “无条件跳转”。当然,你无法证明喽,我已经指出了语法是 break labelName 了呗,顾左右而言他,何也?

    或者,你想说的是,必须使用 goto 这个关键字的跳转,才叫跳转?
    抬杠了吧!

    c#那个所谓的“严格限制”其实也没有严格到哪里去,限制作用域而已,C 的 goto 难道不限制作用域?

    诚然,goto 属于“不鼓励使用”的那一类,但是硬杠成“不能用”、“不准用”,那就请你解释一下,为什么会存在 break labelName 跳转喽?
    uleh
        92
    uleh  
       2018-11-29 15:36:34 +08:00
    goto 用来实现函数单出口很优雅呀
    弄的我 C++也想用了 :P
    passerbytiny
        93
    passerbytiny  
       2018-11-29 15:56:37 +08:00
    @yulitian888 #90 杠精,找 block
    jzq526
        94
    jzq526  
       2018-11-29 16:14:04 +08:00
    很久以前尝试过 goto,个人感觉用好了挺不错……不过,正如大多数事情一样,能到“好”这个程度的人和事都不多,所以还是不要用为好
    oska874
        95
    oska874  
       2018-11-29 16:24:44 +08:00
    不会。
    前提是别乱用。
    驱动里面大把的 goto。
    tinkerer
        96
    tinkerer  
       2018-11-29 16:40:36 +08:00
    经常用啊... 错误处理
    codechaser
        97
    codechaser  
    OP
       2018-11-29 16:52:16 +08:00
    @passerbytiny 老哥,理性讨论,心平气和。
    alphaprogrammer
        98
    alphaprogrammer  
       2018-11-29 19:23:11 +08:00
    错误处理, 分配资源失败 clean up 非常合适
    Fraotisc
        99
    Fraotisc  
       2018-11-29 20:56:17 +08:00 via Android
    驱动和内核使用 goto 做错误处理等操作,如果你有相似的问题,goto 用起来比 if else 简洁。
    neimenggudehai
        100
    neimenggudehai  
       2018-11-30 08:27:21 +08:00
    还敢用 goto,直接活埋
    1  2  
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2796 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 39ms UTC 13:43 PVG 21:43 LAX 05:43 JFK 08:43
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86