为什么这两个 Golang 整数转换函数会给出不同的结果?

huangapple go评论85阅读模式
英文:

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]&lt;&lt;0) | (data[1]&lt;&lt;8) | (data[2]&lt;&lt;16) | (data[3]&lt;&lt;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 (
	&quot;fmt&quot;
	&quot;runtime&quot;
)

func main() {
	input := []byte{255, 255, 255, 255}
	fmt.Println(runtime.GOARCH, runtime.GOOS, runtime.Version(), &quot;input:&quot;, 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) &lt;&lt; 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) &lt;&lt; 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.

huangapple
  • 本文由 发表于 2014年7月12日 06:01:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/24707261.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定