Golang中MulUintptr实现原理

前言

  • 最近在看channel源码时,看到一个函数MulUintptr,功能很简单,就是把两个数相乘,看是否越界,在golang很多地方都有使用,用于判断内存申请
  • 如果越界就返回false,否则返回true
    ,代码如下

go/sys/MulUintptr源码链接

  
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package math

import "runtime/internal/sys"

const MaxUintptr = ^uintptr(0)

// MulUintptr returns a * b and whether the multiplication overflowed.
// On supported platforms this is an intrinsic lowered by the compiler.
func MulUintptr(a, b uintptr) (uintptr, bool) {
	if a|b < 1<<(4*sys.PtrSize) || a == 0 {
		return a * b, false
	}
	overflow := b > MaxUintptr/a
	return a * b, overflow
}

说明

  • 没搞明白的点在于a|b < 1<<(4*sys.PtrSize) || a== 0,看了半天没看懂
  • 在网上查了一下,只发现了用法,也没找到为什么这么写
  • 最后晚上下班在车上才终于想明白

分析

  • 首先a==0,没什么可说的,如果a=0,那么肯定不会越界

  • 重点落在了**a|b < 1<<(4*sys.PtrSize) **

  • sys.PtrSize在64位机器中为8,所以上面的代码等价于a|b < 1<<32

  • 我们知道64位计算中最大的无符号数是2^64-1

  • 看到232和264,再联想到函数的作用是乘法,一下子就明白了

  • 有两个条件要达成共识

    • 相乘的两个数很少会特别大,很少会大于等于2^32
    • 当a|b<232时,则a<232, b<2^32
      • 位运算,这个应该大家都了解
  • 由此得出,如果要判断两个相乘是否大于等于264,只要这两个数都小于232就可以了

  • 这种情况可覆盖99.9%的情况

  • 剩下的情况用verflow := b > MaxUintptr/a就能兜底了

翻译一下代码如下

func MulUintptr(a, b uintptr) (uintptr, bool) {
	if a和b都小于2^32 或者 a 等于 0 时{
		return a * b, 越界
	}
    // a*b如果越界了,得到的数一定比2^64-1小
	overflow := b > MaxUintptr/a
	return a * b, overflow
}

字节跳动长期招聘,欢迎投递
字节跳动内推链接:https://job.bytedance.com/referral/pc/autumn-referral?category=&location=&token=MzsxNjAzOTUzMDMxMzY3OzY4MjAwNjY4ODc4ODg1MzcxMDI7MA

欢迎投递加入~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值