英文:
what's wrong with golang constant overflows uint64
问题
这段代码中的问题是整数溢出。在Go语言中,整数类型的范围是有限的,超出范围的整数会导致溢出错误。根据错误信息,常量-18446462598732840961超出了int类型的范围。
要解决这个问题,你可以考虑使用更大的整数类型,比如int64。修改代码如下:
userid := int64(12345)
did := (userid &^ (0xFFFF << 48))
这样做可以确保整数不会溢出,并且得到正确的结果。
英文:
userid := 12345
did := (userid & ^(0xFFFF << 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 := 12345
,userid
的类型是 int
。然后当你尝试使用无类型常量 -0xffff000000000001
进行按位与(&
)运算时,编译器会认为这个常量应该是一个 int
类型。此时,编译器会报错,因为这个值的大小超过了 int
类型所能表示的范围。
如果你想要得到常量 0x0000ffffffffffff
,你可以使用 1<<48 - 1
,如果你使用的是64位整数,它会适合。由于如果 int
是32位的话,你的代码永远不会工作,所以你应该在代码中使用 int64
而不是 int
,以保证代码的可移植性。
这篇博文 https://blog.golang.org/constants 解释了常量的工作原理,以及它们为什么是这样的背景知识。
英文:
^(0xFFFF << 48)
is an untyped constant, which in go is an arbitrarily large value.
0xffff << 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 (&
) 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<<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 位。
userid
是 int
类型。例如,
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 "fmt"
func main() {
userid := 12345
did := uint64(userid) & ^uint64(0xFFFF<<48)
fmt.Println(userid, did)
}
Output:
12345 12345
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论