只需仔细检查。在一些教程中我找到了这样的代码:
#include <iostream>
using namespace std;
/* This program shows the difference between
* signed and unsigned integers.
*/
int main()
{
short int i; // a signed short integer
short unsigned int j; // an unsigned short integer
j = 50000;
i = j;
cout << i << " " << j;
return 0;
}
输出:-15536 50000
然后它解释了输出:&#34;上面的结果是因为表示50,000作为短无符号整数的位模式被短路解释为-15,536。&#34; < / p>
我认为这是一个错误的解释 - 或者这是一个英文问题? 我认为输出负值的原因是50000不适合2字节符号int,我错了吗?
答案 0 :(得分:3)
您的答案和书籍答案是正确的
50000 = 0xc350
包含0xc350的带符号16位短整数被解释为-15,536
所以它们是正确的(位模式的解释)
如果我是32位int,那么将0xc350放入其中将被解释为50,000
所以你是对的(我太小了)
答案 1 :(得分:3)
对于特定平台,解释中的推理可能是准确的,但在我看来,它与最终打印的内容无关。说起来会更准确
“上述结果是因为从
unsigned short int
值50000到signed short int
的实现定义转换返回的位模式导致值为-15,536。”
并不令人震惊,将所述值发送到std::cout
将为所述值的signed short int
结果生成正确的输出。更改(转换)的源很重要,在这种情况下,它是实现定义的。他们的措辞很弱,并且相同的语句可以通过将任何值分配给任何整数值来应用,所以实际上他们的解释最终是< EM>无意义。
不想浪费之前的答案(在我更好地理解问题之前),享受一些轻松的阅读。要知道肯定为什么会发生这种情况,您必须参考您的实施文档以了解这种性质的转换。不是你可能想听到的答案,但背后有理由。
这是因为值促销通过整数转换排名而发生的。实际上,您收到的价值取决于实施,标准中涵盖了具体原因。
我会遗漏最基本的东西,然后了解它的内容:
C ++11§4.7整体促销[conv.integral]
整数类型的prvalue可以转换为另一个整数类型的prvalue。可以将未范围的枚举类型的prvalue转换为整数类型的prvalue。
如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)。 [注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断)。 - 尾注]
如果目标类型已签名,则该值如果可以在目标类型(和位字段宽度)中表示,则不会更改;否则,该值是实现定义的。
如果目的地类型是bool,请参阅4.12。如果源类型为bool,则将值false转换为零,将值true转换为一个。
- 醇>
整数转化允许的转化不包含在整数转化中。
您的平台上的signed short int
无法表示值50000。因此,结果是实现定义的。从它的外观来看,你的实现只是将字节从一个存储到另一个,结果是符号位(在标准中也包含但为了简洁而省略)被点亮并且报告的数字是负数。但请记住,这是实现定义的,您不能在所有平台上依赖此结果。
答案 2 :(得分:1)
首先,需要使用纯二进制系统来表示整数类型,到目前为止,教程是正确的。
其次,short
必须至少为16位。如果它更多,那么你将看不到你所做的效果或任何效果。从您的描述中不清楚该教程是否盲目地假设short
必然是16位(错误),或者它是否只是使用某些具体示例,并且理解它依赖于编译器等。
第三,如果无法表示值,则转换为签名类型... 是正式的实现定义行为。这意味着您无法保证价值的变化。相反,你可以原则上可以获得任何效果,例如崩溃。
[缺少其他行为的例子,因为我无法将g ++ 4.8.2哄骗到示例代码的陷阱中,即使使用 -ftrapv
]
...产生的值相同,如果可以表示,或者由实现定义。
也就是说,C ++保证无符号算术以模2 n 的形式执行,其中 n 是数字值表示位,例如你的例子中有16个。使用非常常见的二进制补码形式表示有符号整数,负整数值 - x 表示为 - x + 2的位模式 名词 。因此,如果从后一个值(将bitpattern的解释为无符号)开始为50 000,具有16个值位和2的补码形式,则得到有符号值50 000 - 2 16 = 50 000 - 65 536 = -15 536
答案 3 :(得分:0)
50,000以二进制表示为 - 1100 0011 0101 0000。
在有符号位中,最左边的位是符号。在有符号整数中,'0'表示负数(因此为-15536),其中在无符号整数中,这将没有区别。至于数字本身发生变化的原因,我不知道。
答案 4 :(得分:0)
你是对的,这本书也是正确的。 unsigned short
的值可以是0到65535. signed short
的值可以是-32768到32767.因此,0到32767之间的任何值都适用于signed
和{{1} }。
但是,50000这样的数字对于unsigned
来说太大了,所以当您将{500}分配给signed short
时,会导致数字溢出。
答案 5 :(得分:0)
unsigned short
是一个不使用符号位的16位值 - 假设所有值都是正值。
二进制存储的十进制值50,000是
1100 0011 0101 0000
^
最左边的位(最高有效位 - MSB)为1
,代表2^15
,即32,768
整个位模式是32,768 + 16,384 + 512 + 256 + 64 + 16 = 50,000
当您将其转换为签名短片时,位模式未更改,但MSB不再代表32,768 - 它现在代表符号< / em>的数字,其余的位是值的2的补码。在有符号值中,该顶部位是符号,1是负数。
这不会发生在30,000,因为那是
0111 0101 0011 0000
^
当转换为 signed 时,最左边的0
表示符号,0表示正,因此其余位仍然被解释为它们不是二元补码,因此它们仍然代表相同的值30,000