二进制补码和 fmt.Printf:解开二进制表示之谜
处理有符号整数时,计算机使用二进制补码来表示负值。这与典型的二进制表示不同,其中符号由单独的位指示。例如,在二进制补码中,整数 -5 表示为 1111 1011。
但是,使用 fmt.Printf 打印二进制表示形式可能会产生意外结果。例如,以下代码片段:
var i int8 = -5 fmt.Printf("%b", i)
令人惊讶地输出 -101 而不是 1111 1011。这种差异导致了一个问题:二进制补码是否真正用于内部表示,或者格式是否模糊正确的表示。
为了阐明这个问题,我们需要深入研究 fmt.Printf 如何格式化二进制数字。罪魁祸首在于 fmt.integer 函数,该函数自动将负符号整数转换为正整数。此转换涉及对整数取反并在输出字符串前面添加一个 - 符号。因此,-101 输出是 - 的表示形式,附加到 5 的二进制表示形式之后。
为了进一步演示这一点,将有符号整数转换为无符号整数,然后使用 fmt.Printf 对其进行格式化,生成正确的 Two's补码表示:
var u uint8 = uint(i) fmt.Printf("%b", u)
输出 11111011,正好是 -5 的补码。
因此,Go 中带符号整数的内部表示遵循补码习俗。格式化有符号整数时看似不正确的二进制表示是由 fmt.integer 执行的自动转换和符号前置造成的。在 Go 中使用有符号整数和二进制表示时,理解这种行为至关重要。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3