go - Go 允许算术运算溢出而不是抛出异常是预期的行为吗?
问题描述
我正在将一些 Go 代码移植到 Rust,并且我意识到当乘法期间发生溢出时 Rust 会发生恐慌,而 Go 允许发生溢出。
下面的测试代码,不会导致溢出但打印减少的值。(通过:https ://play.golang.org/ 测试)
func main() {
fmt.Println("test\n")
var key uint64 = 15000;
key = key*2862933555777941757 + 1
fmt.Println(key)
}
解决方案
对于无符号整数值,运算 +、-、* 和 << 以 2 n为模计算,其中n是无符号整数类型的位宽。粗略地说,这些无符号整数运算在溢出时会丢弃高位,并且程序可能依赖于“环绕”。
对于有符号整数,操作 +、-、*、/ 和 << 可能合法溢出,并且结果值存在并且由有符号整数表示、操作及其操作数确定性地定义。溢出不会导致运行时恐慌。在不发生溢出的假设下,编译器可能不会优化代码。例如,它可能并不认为这
x < x + 1
总是正确的。
如上所述,溢出存在并且它不会导致运行时恐慌。
但是必须小心,就好像你有一个常量表达式一样,因为它们具有任意精度,如果要将结果转换为不适合目标类型有效范围的固定精度,则会导致编译时间 -错误。
例如:
const maxuint64 = 0xffffffffffffffff
var key uint64 = maxuint64 * maxuint64
fmt.Println(key)
以上产生:
constant 340282366920938463426481119284349108225 overflows uint64
maxuint64 * maxuint64
是一个经过正确计算的常量表达式(其值为340282366920938463426481119284349108225
),但是当将此值分配给key
type 的变量时uint64
,会导致编译时错误,因为该值不能由 type 的值表示uint64
。但这不是运行时恐慌。
查看相关问题:
推荐阅读
- javascript - this 没有 new 关键字
- c++ - 我可以将 void* 转换为 unique_ptr 吗?
- javascript - Node JS 服务器,无法获取 index.html
- mysql - 使用group by function时选择特定的id [MySQL]
- kdb - 使用设置窗口计算 2 个列表的加权移动平均值
- python - 在 python 类中引用整数作为静态变量
- c# - Asp.net core 返回 View 或 Json/XML 的最干净方式
- javascript - 点击跟踪的高阶 React 组件
- r - 如何为数据框中的所有分类变量制作频率表?
- javascript - php curl 使用 html 下拉选择填充变量