0

How do you convert a float32 pointer *float32 to a float64 pointer *float64.

package main

import "fmt"

func main() {
    var value *float32
    v := float64(*value)
    vp := &v
    fmt.Println(vp)
}

The following code returns

runtime error: invalid memory address or nil pointer dereference

3
  • 2
    As the error says, value is nil when you try to dereference it. It doesn't point to anything as it hasn't been initialized. Commented Nov 10, 2022 at 14:58
  • Did you mean to include var x float32 = 0; var value *float32 = &x or something like that? play.golang.com/p/XlC3H1T7g9R Commented Nov 10, 2022 at 15:01
  • 3
    When you don't understand what's going on, "seemingly simple" is not necessarily so. You can't get a float32 value to convert if the pointer is nil, hence you need a conditional of some sort to get it, along with a new memory location to store the converted value. If direct type casting were allowed (which you could still do with unsafe) you would end up with a pointer to an invalid value. Commented Nov 10, 2022 at 16:51

2 Answers 2

2

The reason your code is failing is simply that you are trying to dereference a pointer that has not been initialised:

    var value *float32 

declares a pointer to a float32, but does not initialise it, resulting in a nil pointer.

    v := float64(*value)

Then tries to dereference value but as we just identified, value is nil - it doesn't point to anything so asking for what it points to is bound to result in an error.

However, your code is actually fine, as long as you have a *float32 that actually points to a float32, which we can see if we add an actual float32 variable and initialise value to point to that:

package main

import "fmt"

func main() {
    var vv float32 = 3.14159
    var value *float32 = &vv
    v := float64(*value)
    vp := &v
    fmt.Println(vp)
}

Which will output the address of the float64 value.

However, be aware that a float64 is not just a float32 that takes up twice as many bytes. The precision and the internal representation are different, as can be seen with a further modification to the code:

func main() {
    var vv float32 = 3.14159
    var value *float32 = &vv
    v := float64(*value)
    fmt.Println(vv)
    fmt.Println(v)
}

you should see output similar to:

3.14159
3.141590118408203

This is not a bug, this is the result of the different internal representation of a float64 vs float32.

There is no way to guarantee the exact same value in these different types - each has characteristics that make some values literally impossible to represent, from which it follows that it is impossible to guarantee that float32(v) == float64(v) for every v.

This is also why you cannot simply type-cast the pointer:

    vp := *float64(value)

This is illegal because a pointer to a float64 is pointing to something fundamentally different than a pointer to a float32.

By contrast you can simply typecast a *int32 as a *int64.

Sign up to request clarification or add additional context in comments.

Comments

2

One method is to write a function to safely convert the float32 pointer to a float64 pointer.

package main

import "fmt"

func main() {
    var value *float32
    v := float32ToFloat64(value)
    fmt.Println(v)

    val := float32(1.2)
    p := float32ToFloat64(&val)
    fmt.Println(*p)
}

func float32ToFloat64(value *float32) *float64 {
    if value == nil {
        return nil
    }
    v := float64(*value)
    return &v
}

2 Comments

You can just return nil in the nil case, you don't need to declare a new variable.
Besides JimB's comment (play.golang.com/p/mbVEislliFU), this looks fine. You create a new value of the size you want, and return a pointer to it. If you want a float64, you're going to have to make one eventually. And if you want a pointer to something, you're going to need to store it somewhere. So this feels pretty much the minimum work needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.