golang 和 C 之间以十六进制形式打印 64 位整数 -1 的格式有所不同

cli*_*i__ 0 go

我最近正在阅读effective_go文档,并对%x整数值的格式打印-1结果感到震惊"-1":

var x uint64 = 1<<64 - 1
fmt.Printf("%d %x; %d %x\n", x, x, int64(x), int64(x))
Run Code Online (Sandbox Code Playgroud)

印刷

18446744073709551615 ffffffffffffffff; -1 -1
Run Code Online (Sandbox Code Playgroud)

来自C语言我假设的输出%x int64(x)也应该是ffffffffffffffff,我想这就是最初的目的是%x吗?你见过十六进制数前面有一个符号吗?像这样?

-1
-3A
-A3
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 5

例如,Go 在这里的行为与 C 不同。%x整数的动词意味着使用十六进制(基数 16)表示形式来格式化数字的值,而不是其内存表示形式(这将是 2 的补码)。%b对于二进制和%o八进制表示也是如此。

对于像 之类的负数-255,其 16 进制表示为-ff。

Go 对类型很严格,你必须始终明确。如果传递有符号整数,它将被格式化为有符号整数。如果要将其打印为无符号值,则必须将其显式转换为无符号值,如下例所示:

i := -1 // type int
fmt.Printf("%d %x %d %x", i, i, uint(i), uint(i))
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上尝试):

-1 -1 4294967295 ffffffff
Run Code Online (Sandbox Code Playgroud)

请注意,当将有符号值转换为其无符号版本(相同大小)时,它不会更改内存表示形式,只是更改其类型,因此转换后的值(无符号结果)将是有符号值的 2 补码。

至于为什么这是负数的默认值,请阅读 Rob Pike 给出的推理:

为什么这不是默认的[无符号格式]?因为如果是这样,就无法将某些内容打印为负数,正如您所看到的,负数的表示形式要短得多。或者换句话说,%b %o %d %x 都以相同的方式对待它们的参数。

您可以在这个相关问题中看到这是如何/在哪里实现的:Golang: Two's Complement and fmt.Printf