为什么在 C++ 中将 signed char 分配给 unsigned char 时从 256 中减去?
Why subtract from 256 when assigning signed char to unsigned char in C++?
在 Bjarne 的《The C++ Programming Language》一书中,给出了以下一段关于 chars 的代码:
signed char sc = -140;
unsigned char uc = sc;
cout << uc // prints 't'
1Q) 字符在我的硬件中是 1 字节(8 位)。 -140
的二进制表示是什么?是否可以使用 8 位来表示 -140。我认为在考虑签名字符时,范围保证至少为 [-127...127]。怎么可能用 8 位表示 -140?
2Q) 假设这是可能的。当 sc
分配给 uc
时,为什么我们从 uc
中减去 140
?这背后的逻辑是什么?
编辑: 我写了 cout << sizeof (signed char)
并且它产生了 1(1 个字节)。我把它放在 signed char
.
的字节大小上
编辑 2: cout << int {sc }
给出输出 116
。我不明白这里发生了什么?
将 -140 分配给 signed char
的结果是实现定义的,就像它的范围一样(即参见手册)。一个非常常见的选择是使用环绕数学:如果它不适合,加或减 256(或相关的最大范围)直到它适合。
由于 sc
的值为 116,而 uc
也可以保存该值,因此转换很简单。当我们将 -140 分配给 sc
.
时,不寻常的事情已经发生了
首先:除非你正在编写需要位表示操作的非常低级的东西 - 避免像瘟疫一样编写这种代码。它难以阅读、容易出错、令人困惑,并且经常表现出 implementation-defined/undefined 行为。
虽然要回答你的问题:
代码假定您所处的平台上类型 signed char
和 unsigned char
有 8 位(尽管理论上它们可以有更多位)。并且硬件具有 "two's complement" 行为:对具有 N 位的整数类型的算术运算结果的位表示始终为模 2^N。这也指定了如何将相同的位模式解释为有符号或无符号。现在,-140 模 2^8 是 116 (01110100),因此位模式 sc
将成立。解释为带符号的字符(-128 到 127),这仍然是 116。
一个unsigned char
也可以表示116
,所以第二个赋值结果也是116。
116是字符t
的ASCII code; std::cout
将 unsigned char
值(小于 128)解释为 ASCII 码。所以,这就是打印的内容。
在 Bjarne 的《The C++ Programming Language》一书中,给出了以下一段关于 chars 的代码:
signed char sc = -140;
unsigned char uc = sc;
cout << uc // prints 't'
1Q) 字符在我的硬件中是 1 字节(8 位)。 -140
的二进制表示是什么?是否可以使用 8 位来表示 -140。我认为在考虑签名字符时,范围保证至少为 [-127...127]。怎么可能用 8 位表示 -140?
2Q) 假设这是可能的。当 sc
分配给 uc
时,为什么我们从 uc
中减去 140
?这背后的逻辑是什么?
编辑: 我写了 cout << sizeof (signed char)
并且它产生了 1(1 个字节)。我把它放在 signed char
.
编辑 2: cout << int {sc }
给出输出 116
。我不明白这里发生了什么?
将 -140 分配给 signed char
的结果是实现定义的,就像它的范围一样(即参见手册)。一个非常常见的选择是使用环绕数学:如果它不适合,加或减 256(或相关的最大范围)直到它适合。
由于 sc
的值为 116,而 uc
也可以保存该值,因此转换很简单。当我们将 -140 分配给 sc
.
首先:除非你正在编写需要位表示操作的非常低级的东西 - 避免像瘟疫一样编写这种代码。它难以阅读、容易出错、令人困惑,并且经常表现出 implementation-defined/undefined 行为。
虽然要回答你的问题:
代码假定您所处的平台上类型 signed char
和 unsigned char
有 8 位(尽管理论上它们可以有更多位)。并且硬件具有 "two's complement" 行为:对具有 N 位的整数类型的算术运算结果的位表示始终为模 2^N。这也指定了如何将相同的位模式解释为有符号或无符号。现在,-140 模 2^8 是 116 (01110100),因此位模式 sc
将成立。解释为带符号的字符(-128 到 127),这仍然是 116。
一个unsigned char
也可以表示116
,所以第二个赋值结果也是116。
116是字符t
的ASCII code; std::cout
将 unsigned char
值(小于 128)解释为 ASCII 码。所以,这就是打印的内容。