英文:
Why do these two golang integer conversion functions give different results?
问题
我写了一个将字节切片转换为整数的函数。
我创建的函数实际上是基于循环的实现,参考了Rob Pike在这里发布的内容:
http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
这是Rob的代码:
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
我的第一个实现(playground中的toInt2函数)不像我预期的那样工作,因为它似乎将int值初始化为uint。这看起来非常奇怪,但它必须是特定于平台的,因为go playground报告的结果与我的机器(mac)不同。
有人能解释一下为什么这些函数在我的mac上表现不同吗?
这是带有代码的playground链接:http://play.golang.org/p/FObvS3W4UD
这是playground中的代码(为了方便起见):
/*
在我的机器上的输出:
amd64 darwin go1.3 input: [255 255 255 255]
-1
4294967295
在go playground上的输出:
amd64p32 nacl go1.3 input: [255 255 255 255]
-1
-1
*/
package main
import (
"fmt"
"runtime"
)
func main() {
input := []byte{255, 255, 255, 255}
fmt.Println(runtime.GOARCH, runtime.GOOS, runtime.Version(), "input:", input)
fmt.Println(toInt(input))
fmt.Println(toInt2(input))
}
func toInt(bytes []byte) int {
var value int32 = 0 // 初始化为int32
for i, b := range bytes {
value |= int32(b) << uint(i*8)
}
return int(value) // 转换为int
}
func toInt2(bytes []byte) int {
var value int = 0 // 初始化为普通的int
for i, b := range bytes {
value |= int(b) << uint(i*8)
}
return value
}
英文:
I wrote a function to convert a byte slice to an integer.
The function I created is actually a loop-based implemtation of
what Rob Pike published here:
http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
Here is Rob's code:
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
My first implementation (toInt2 in the playground) doesn't work as
I expected because it appears to initialize the int value as a uint.
This seems really strange but it must be platform specific because
the go playground reports a different result than my machine (a mac).
Can anyone explain why these functions behave differently on my mac?
Here's the link to the playground with the code: http://play.golang.org/p/FObvS3W4UD
Here's the code from the playground (for convenience):
/*
Output on my machine:
amd64 darwin go1.3 input: [255 255 255 255]
-1
4294967295
Output on the go playground:
amd64p32 nacl go1.3 input: [255 255 255 255]
-1
-1
*/
package main
import (
"fmt"
"runtime"
)
func main() {
input := []byte{255, 255, 255, 255}
fmt.Println(runtime.GOARCH, runtime.GOOS, runtime.Version(), "input:", input)
fmt.Println(toInt(input))
fmt.Println(toInt2(input))
}
func toInt(bytes []byte) int {
var value int32 = 0 // initialized with int32
for i, b := range bytes {
value |= int32(b) << uint(i*8)
}
return int(value) // converted to int
}
func toInt2(bytes []byte) int {
var value int = 0 // initialized with plain old int
for i, b := range bytes {
value |= int(b) << uint(i*8)
}
return value
}
答案1
得分: 3
这只是一个有根据的猜测,但是int
类型的大小取决于平台,可能是64位或32位。在我的系统和你的系统上,它是64位的,因为Playground是在nacl上运行的,它是32位的。
如果你将第二个函数中的所有类型改为uint
,它将正常工作。
根据规范:
uint
:可以是32位或64位int
:与uint
大小相同uintptr
:一个足够大的无符号整数,用于存储指针值的未解释位
英文:
This is an educated guess, but int
type can be 64bit or 32bit depending on the platform, on my system and yours it's 64bit, since the playground is running on nacl, it's 32bit.
If you change the 2nd function to use uint all around, it will work fine.
From the spec:
uint either 32 or 64 bits
int same size as uint
uintptr an unsigned integer large enough to store the uninterpreted bits of a pointer value
答案2
得分: 1
int
允许使用32位或64位,具体取决于平台/实现。当它是64位时,在您的计算机上,它能够表示2^32
作为有符号正整数。当它是32位时(在playground中),它会按照您的预期发生溢出。
英文:
int
is allowed to be 32 or 64 bits, depending on platform/implementation. When it is 64-bits, it is capable of representing 2^32
as a signed positive integer, which is what happens on your machine. When it is 32-bits (the playground), it overflows as you expect.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论