Golang常量溢出uint64的问题是什么?

huangapple go评论89阅读模式
英文:

what's wrong with golang constant overflows uint64

问题

这段代码中的问题是整数溢出。在Go语言中,整数类型的范围是有限的,超出范围的整数会导致溢出错误。根据错误信息,常量-18446462598732840961超出了int类型的范围。

要解决这个问题,你可以考虑使用更大的整数类型,比如int64。修改代码如下:

userid := int64(12345)
did := (userid &^ (0xFFFF << 48))

这样做可以确保整数不会溢出,并且得到正确的结果。

英文:
userid := 12345
did := (userid &amp; ^(0xFFFF &lt;&lt; 48))

when compiling this code, I got:

> ./xxxx.go:511: constant -18446462598732840961 overflows int

Do you know what is the matter with this and how to solve it ?
Thanks.

答案1

得分: 11

^(0xFFFF << 48) 是一个无类型常量,在Go语言中它是一个任意大的值。

0xffff << 48 等于 0xffff000000000000。当你对它取反时,得到的是 -0xffff000000000001(因为使用二进制补码,-x = ^x + 1,或者^x = -(x + 1))。

当你写 userid := 12345userid 的类型是 int。然后当你尝试使用无类型常量 -0xffff000000000001 进行按位与(&)运算时,编译器会认为这个常量应该是一个 int 类型。此时,编译器会报错,因为这个值的大小超过了 int 类型所能表示的范围。

如果你想要得到常量 0x0000ffffffffffff,你可以使用 1<<48 - 1,如果你使用的是64位整数,它会适合。由于如果 int 是32位的话,你的代码永远不会工作,所以你应该在代码中使用 int64 而不是 int,以保证代码的可移植性。

这篇博文 https://blog.golang.org/constants 解释了常量的工作原理,以及它们为什么是这样的背景知识。

英文:

^(0xFFFF &lt;&lt; 48) is an untyped constant, which in go is an arbitrarily large value.

0xffff &lt;&lt; 48 is 0xffff000000000000. When you negate it, you get -0xffff000000000001 (since with two's complement, -x = ^x + 1, or ^x = -(x + 1)).

When you write userid := 12345, userid gets the type int. Then when you try to and (&amp;) it with the untyped constant -0xffff000000000001 the compiler figures that this constant needs to be an int. At this point, the compiler complains because the value is too large in magnitude to be an int.

If you're trying to get the constant 0x0000ffffffffffff, then you can use 1&lt;&lt;48 - 1, which (if you've got 64-bit ints), will fit. Since your code will never work if int is 32-bits, then you should probably use int64 in your code rather than int to make it portable.

The blog post https://blog.golang.org/constants explains how constants work, and some background on why they are the way they are.

答案2

得分: 2

《Go编程语言规范》

常量

数值常量表示任意精度的值,不会溢出。

常量可以是有类型的或无类型的。

常量可以通过常量声明或转换显式地指定类型,也可以在变量声明、赋值或表达式中隐式地使用时自动获得类型。如果常量的值不能表示为相应类型的值,则会报错。

无类型常量有一个默认类型,在需要有类型值的上下文中,会隐式地将其转换为该类型。例如,在没有显式类型的情况下,可以使用短变量声明 i := 0 来声明一个无类型常量。无类型常量的默认类型分别是 bool、rune、int、float64、complex128 或 string,具体取决于它是布尔、符文、整数、浮点数、复数还是字符串常量。

数值类型

int 是一个实现特定的大小,可以是 32 位或 64 位。

useridint 类型。例如,

package main

import "fmt"

func main() {
    userid := 12345
    did := uint64(userid) & ^uint64(0xFFFF<<48)
    fmt.Println(userid, did)
}

输出:

12345 12345
英文:

> The Go Programming Language Specification
>
> Constants
>
> Numeric constants represent values of arbitrary precision and do not
> overflow.
>
> Constants may be typed or untyped.
>
> A constant may be given a type explicitly by a constant declaration or
> conversion, or implicitly when used in a variable declaration or an
> assignment or as an operand in an expression. It is an error if the
> constant value cannot be represented as a value of the respective
> type.
>
> An untyped constant has a default type which is the type to which the
> constant is implicitly converted in contexts where a typed value is
> required, for instance, in a short variable declaration such as i := 0
> where there is no explicit type. The default type of an untyped
> constant is bool, rune, int, float64, complex128 or string
> respectively, depending on whether it is a boolean, rune, integer,
> floating-point, complex, or string constant.
>
> Numeric types
>
> int is an implementation-specific size, either 32 or 64 bits.

userid is of type int. For example,

package main

import &quot;fmt&quot;

func main() {
	userid := 12345
	did := uint64(userid) &amp; ^uint64(0xFFFF&lt;&lt;48)
	fmt.Println(userid, did)
}

Output:

12345 12345

huangapple
  • 本文由 发表于 2015年4月22日 11:51:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/29787422.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定