我最近正在阅读 effective_go文档,并震惊地发现 %x
格式打印整数值 -1
结果为 "-1"
:
var x uint64 = 1<<64 - 1
fmt.Printf("%d %x; %d %x\n", x, x, int64(x), int64(x))
打印
18446744073709551615 ffffffffffffffff; -1 -1
来自C语言我假设%x int64(x)
的输出也应该是ffffffffffffffff
,我认为这是%x的初衷
是吗?你见过十六进制数前面加个符号吗?像这样?
-1
-3A
-A3
例如,Go 在这里的行为与 C 不同。整数的 %x
动词表示使用十六进制(以 16 为基数)表示形式格式化数字的值,而不是其内存表示形式(将是 2 的补码)。二进制表示的 %b
和八进制表示的 %o
也是如此。
对于像-255
这样的负数,它的base16表示是-ff
。
Go 对类型很严格,你总是必须明确。如果您传递有符号整数,它将被格式化为有符号整数。如果要将其打印为无符号值,则必须将其显式转换为无符号值,如本例所示:
i := -1 // type int
fmt.Printf("%d %x %d %x", i, i, uint(i), uint(i))
输出(在 Go Playground 上尝试):
-1 -1 4294967295 ffffffff
请注意,当将有符号值转换为其无符号版本(相同大小)时,它不会仅更改其类型的内存表示,因此转换后的值(无符号结果)将是有符号值的 2 的补码。
至于为什么这是负数的默认值,请阅读 Rob Pike 给出的推理 here :
Why is that not the default [the unsigned format]? Because if it were, there would be no way to print something as a negative number, which as you can see is a much shorter representation. Or to put it another way, %b %o %d %x all treat their arguments identically.
您可以在这个相关问题中看到这是如何/在何处实现的:Golang: Two's complement and fmt.Printf