编程语言 / 跳转 · 2023年 10月 14日 0

goto关键字

122 次浏览

提到goto, 大家一定能想到迪杰斯特拉发表的著名论文goto有害论(Go To Statement Considered Harmful)。正是它推动了结构化程序设计语言的发展。公正地说,goto并非那么可怕,机器码/汇编码本身支持跳转,就是goto的底层形态。计算机程序中条件选择、循环等语句最终依然依靠跳转指令完成,只是高级编程语言不建议用goto, 会造成程序员的困扰。但,机器从来都没困扰过,CPU根据jmp或j*指令的地址改写RIP地址并执行,丝滑无比,从未抱怨过。

"万恶"的goto

  • 越靠近底层的语言可能会支持goto,例如汇编和C/C++, 更高级的编程语言尽可能废弃goto, C#又是个特例,它也支持goto.
  • goto就像一个小孩子,一会哭一会闹,完全get不到他想要什么。但如果是一个专业的技术员,goto能发挥他最大能力,因为他随时都知道应该去哪里做什么。
  • “goto是魔鬼”并不总正确。内核和驱动代码为了更鲁棒,有健全的出错处理机制,出错处理一般会被定义成label, 在出错情形较多时用goto是最佳化跳转,而不是多种条件判断出错处理。
  • Rust改进C语言出错处理逻辑,避免过多判断,引入match语句匹配OK或fail场景,更清晰可靠。
  • Go语言是C语言的进化版,引入defer语句解决延迟错误处理,避免C语言大量出错处理。
  • PHP和C语言类似,也支持goto.

goto的内部实现

  • goto是无条件跳转,可对应汇编jmp.
  • 汇编代码隐式包含所在代码”地址”, 程序员可以手动加上任意label给goto提供跳转位置。
    • 当然也可以根据汇编代码的堆栈相对位置(如EBP/ESP/PC)跳转,不需要额外定义label.
    • 标签label服务于程序员和编译器,不会增加机器码长度。
  • break/continue/return本质都是可控/受限的”goto”.
  • 当然,关键字和数字不能当做label.

不同编程语言的goto

  • C# 除支持普通的goto identifier, 也支持switch语句中goto case condition和goto default.