【问题标题】:Output of a short int and a unsigned short?短整数和无符号短的输出?
【发布时间】:2017-01-24 16:44:16
【问题描述】:

所以我试图解释以下输出:

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 时,哪些操作会导致此结果?

【问题讨论】:

  • 对我来说很合适。你期待什么结果?
  • @SteveSummit 实际上这对我来说似乎不正确......根据port70.net/~nsz/c/c11/n1570.html#6.3.1.3p2 它应该是53190。如果我没看错……
  • @EugeneSh。您没有正确阅读它;-)
  • @P.P.请解释这个是从哪里来的
  • @P.P.哦!没关系。我已经阅读了大约 10 次,直到正确为止。

标签: c unsigned twos-complement


【解决方案1】:

我的答案假设16-bit 二进制补码算法。

要找到-12345 的值,取12345,补全,然后加上1

12345 is 0x3039 is 0011000000111001.

互补意味着将所有1's 更改为0's 并将所有0's 更改为1's:

1100111111000110 is 0xcfc6 is 53190.

加一个:53191

所以在内部,-123450xcfc7 = 53191 表示。

但如果你把它解释为一个无符号数,它显然只是53191。 (并且当您将有符号值分配给相同大小的无符号整数时,通常最终会发生的是您分配了确切的位模式,而不进行任何转换。但是,稍后您通常会以不同的方式解释该值,例如当你用%u打印它。)

另一种可能更简单的思考方式是 16-bit 算术“环绕”在 216 = 65536。因此您可以将 65536 视为 @987654338 的另一个名称@(就像 0:0024:00 都是午夜的名称)。所以-1234565536 - 12345 = 53191

【讨论】:

  • 非常感谢...我正在这样做,但不知何故我迷路了。最后一句真的是一个很好的看待它的方式。 :) 谢谢你
  • 答案的第一部分与C语言上下文中的问题无关。该行为不依赖于机器的“2-complementness”。转换和重新解释是两个完全不同的概念。在这种情况下,我们正在处理转换。根本不涉及重新解释。至少可以说,试图通过重新解释来解释它是一种误导。
  • @AnT 我的回答根本不是为了解决 C 语言:它解释了二进制补码算法,这是 OP 所问的。关于“解释”的括号故意含糊其辞,但我已经改写了一下。
【解决方案2】:

C 标准定义的有符号整数转换为无符号整数的转换规则要求重复将 TYPE_MAX + 1 添加到值。

来自6.3.1.3 Signed and unsigned integers

否则,如果新类型是无符号的,则值转换为 反复加或减一大于最大值 可以用新类型表示,直到值在 新类型。

如果 USHRT_MAX 是 65535,然后加上 65535 + 1 + -1234553191

【讨论】:

    【解决方案3】:

    看到的输出不依赖于 2 的补码,也不依赖于 16 位或 32 位 int。看到的输出是完全定义的,并且在罕见的 1 的补码或符号幅度机器上是相同的。结果确实取决于 16 位 unsigned short

    -12345 在short 的最小范围内,因此该分配没有问题。当 short 作为 ... 参数传递时,人们认为通常提升到 int 的值没有变化,因为所有 short 都在 int 的范围内。 "%d" 需要 int,所以输出是 "-12345"

    short int v = -12345;
    printf("%d\n", v);  // output "-12345\n"
    

    将负数分配给无符号类型是明确定义的。对于 16 位 unsigned shortuv 的值是 -12345 加上 USHRT_MAX+1(在本例中为 65536)的最小倍数到最终值 53191。

    unsigned short 作为 ... 参数传递,值将转换为intunsigned,无论哪种类型包含unsigned short 的整个范围。 IAC,不会改变。 "%u" 匹配 unsigned。它还匹配一个int,其值可以表示为intunsigned

    short int v = -12345;
    unsigned short uv = (unsigned short) v;
    printf("%u\n", v); // output "53191\n"
    

    将值转换为 unsigned short 时,哪些操作会导致此结果?

    选角不影响最终结果。如果没有演员表,同样的结果也会发生。演员表可能对安静的警告很有用。

    【讨论】:

    • 我现在没有...谢谢大家的帮助。这真的帮助我理解了这一点。
    猜你喜欢
    • 1970-01-01
    • 2013-02-16
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多