what's wrong with golang constant overflows uint64

后端 未结 2 784
-上瘾入骨i
-上瘾入骨i 2020-12-20 02:04
userid := 12345
did := (userid & ^(0xFFFF << 48))

when compiling this code, I got:

./xxxx.go:511: constant -

相关标签:
2条回答
  • 2020-12-20 02:50

    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
    
    0 讨论(0)
  • 2020-12-20 02:51

    ^(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.

    0 讨论(0)
提交回复
热议问题