V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
codechaser
V2EX  ›  C

C 中使用 goto 会被打吗?

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

    突发奇想,C 中的 goto 和我以前学的单片机里的汇编跳转好像,感觉很强大啊。假如大型项目里使用 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 +08: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`搜不到你这些
    nanjoyoshino
        23
    nanjoyoshino  
       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 为什么不能用?
    ruimz
        42
    ruimz  
       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 跳到后面
    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  
       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
        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   ·   实用小工具   ·   2949 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 14:17 · PVG 22:17 · LAX 06:17 · JFK 09:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.