Search code examples
pointersgoconstants

Find address of constant in go


We have written one program by which we try to find an address of a constant. Is it possible to do it like that?

package main

func main() {
        const k = 5
        address := &k
}

It gives an error, can anyone tell how can we find the address of a constant?


Solution

  • In short: you can't.

    The error message says:

    cannot take the address of k

    There are limitations on the operand of the address operator &. Spec: Address operators:

    For an operand x of type T, the address operation &x generates a pointer of type *T to x. The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal. If the evaluation of x would cause a run-time panic, then the evaluation of &x does too.

    Constants are not listed as addressable, and things that are not listed in the spec as addressable (quoted above) cannot be the operand of the address operator & (you can't take the address of them).

    It is not allowed to take the address of a constant. This is for 2 reasons:

    1. A constant may not have an address at all.
    2. And even if a constant value is stored in memory at runtime, this is to help the runtime to keep constants that: constant. If you could take the address of a constant value, you could assign the address (pointer) to a variable and you could change that (the pointed value, the value of the constant). Robert Griesemer (one of Go's authors) wrote why it's not allowed to take a string literal's address: "If you could take the address of a string constant, you could call a function [that assigns to the pointed value resulting in] possibly strange effects - you certainly wouldn't want the literal string constant to change." (source)

    If you need a pointer to a value being equal to that constant, assign it to a variable of which is addressable so you can take its address, e.g.

    func main() {
        const k = 5
        v := k
        address := &v // This is allowed
    }
    

    But know that in Go numeric constants represent values of arbitrary precision and do not overflow. When you assign the value of a constant to a variable, it may not be possible (e.g. the constant may be greater than the max value of the variable's type you're assigning it to - resulting in compile-time error), or it may not be the same (e.g. in case of floating point constants, it may lose precision).