所以我试图解释以下输出:
short int v = -12345;
unsigned short uv = (unsigned short) v;
printf("v = %d, uv = %u\n", v, uv);
Output:
v = -12345
uv = 53191
所以问题是:为什么在这个程序在双补机上运行时会产生这个确切的输出?
将值转换为unsigned short
时,哪些操作会导致此结果?
答案 0 :(得分:2)
我的回答假定16-bit
两个补码算术。
要查找-12345
的值,请点击12345
,补充它,然后添加1
。
12345 is 0x3039 is 0011000000111001.
补充意味着将所有1
更改为0
并将所有0
更改为1
&# 39,S:
1100111111000110 is 0xcfc6 is 53190.
添加一个:53191
。
在内部,-12345
由0xcfc7 = 53191
表示。
但如果你把它解释为无符号数,那么它显然只是53191
。 (当您将有符号值分配给相同大小的无符号整数时,通常最终会发生的是您分配精确的位模式,而不转换任何内容。但是,稍后,您通常会以不同方式解释该值,例如你用%u
打印它。)
另一种可能更容易思考的方法是16-bit
算术"包裹"在2 16 = 65536。因此,您可以将65536
视为0
的另一个名称(就像0:00
和24:00
都是名称午夜)。因此-12345
为65536 - 12345 = 53191
。
答案 1 :(得分:1)
转换规则,当将有符号整数转换为无符号整数时,由C标准定义,需要重复将TYPE_MAX + 1添加到该值。
来自6.3.1.3 Signed and unsigned integers:
否则,如果新类型是无符号的,则转换为 重复加或减一个以上的最大值 可以用新类型表示,直到值在范围内 新类型。
如果USHRT_MAX
为65535,则添加65535
+ 1
+ -12345
为53191
。
答案 2 :(得分:1)
看到的输出不依赖于2的补码,也不依赖于16或32位int
。看到的输出是完全定义的,并且在罕见的1的补码或符号幅度机器上是相同的。结果取决于16位unsigned short
-12345在short
的最小范围内,因此该任务没有问题。当short
作为...参数传递时,会认为通常的促销活动为int
且价值没有变化,因为所有short
都在{{1}的范围内}。 int
需要"%d"
,因此输出为int
"-12345"
明确定义了为无符号类型指定负数。使用16位short int v = -12345;
printf("%d\n", v); // output "-12345\n"
时,unsigned short
的值为-12345加上uv
的最小倍数(本例中为65536),最终值为53191.
将USHRT_MAX+1
作为...参数传递,该值将转换为unsigned short
或int
,无论哪种类型包含unsigned
的整个范围。 IAC,值不会改变。 unsigned short
与"%u"
匹配。它还匹配unsigned
,其值可以表达为int
或int
。
unsigned
将值转换为unsigned short时,哪些操作会导致此结果?
施法并未影响最终结果。如果没有演员阵容,也会发生同样的结果。演员阵容可能有助于安静警告。