英文:
Go: How to convert a float32 pointer to float64 pointer
问题
如何将float32指针*float32
转换为float64指针*float64
。
package main
import "fmt"
func main() {
var value *float32
v := float64(*value)
vp := &v
fmt.Println(vp)
}
上述代码返回以下错误信息:
运行时错误:无效的内存地址或空指针解引用
英文:
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
答案1
得分: 2
一种方法是编写一个函数,将float32指针安全地转换为float64指针。
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
}
英文:
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
得分: 2
你的代码失败的原因很简单,就是你试图解引用一个未初始化的指针:
var value *float32
声明了一个指向 float32
的指针,但没有对其进行初始化,导致它是一个空指针。
v := float64(*value)
然后试图解引用 value
,但正如我们刚刚确定的,value
是空指针 - 它没有指向任何东西,所以要求它指向的内容必然会导致错误。
然而,只要你有一个实际指向 float32
的 *float32
,你的代码实际上是正确的,我们可以看到这一点,如果我们添加一个实际的 float32
变量,并将 value
初始化为指向它:
package main
import "fmt"
func main() {
var vv float32 = 3.14159
var value *float32 = &vv
v := float64(*value)
vp := &v
fmt.Println(vp)
}
这将输出 float64
值的地址。
然而,请注意,float64
不仅仅是占用两倍字节的 float32
。精度和内部表示是不同的,可以通过对代码进行进一步修改来看到:
func main() {
var vv float32 = 3.14159
var value *float32 = &vv
v := float64(*value)
fmt.Println(vv)
fmt.Println(v)
}
你应该看到类似以下的输出:
3.14159
3.141590118408203
这不是一个 bug,这是 float64
和 float32
的不同内部表示的结果。
无法保证这些不同类型的确切相同值 - 每种类型都有一些使得某些值在字面上不可能表示的特性,由此可见,无法保证对于每个 v
,float32(v) == float64(v)
。
这也是为什么你不能简单地将指针进行类型转换的原因:
vp := *float64(value)
这是非法的,因为指向 float64
的指针指向的是与指向 float32
的指针_根本不同_的东西。
相比之下,你可以将 *int32
简单地强制转换为 *int64
。
英文:
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论