【问题标题】:What happens when I assign a negative value to an unsigned int? [duplicate]当我为 unsigned int 分配负值时会发生什么? [复制]
【发布时间】:2011-11-01 10:31:19
【问题描述】:

可能重复:
signed to unsigned conversion in C - is it always safe?

假设我声明了一个 unsigned int 类型的变量:unsigned int x = -1;

现在二进制补码中的 -1(假设是 32 位机器)是 0xFFFFFFFF。 现在,当我将此值分配给 x 时,是否将值 0x7FFFFFFF 分配给 x?

如果是这样,那么 printf ("%d",x);会打印相当于 0x7FFFFFFF 的十进制数,对吧?但是,显然这不会发生,因为打印的值为 -1。我在这里错过了什么?

编辑:我知道我们可以使用 %u 格式说明符来打印无符号值。 但这无助于回答上述问题。

【问题讨论】:

  • 0x7FFFFFFF 是从哪里来的?
  • @Evan:翻转 MSB。只是猜测,因为我不知道转换是如何发生的
  • C99 标准的第 6.3.1.3 节应该回答您的问题。但这应该更好地回答你的问题stackoverflow.com/questions/50605/…

标签: c unsigned


【解决方案1】:

"%d" 格式用于(有符号的)int 值。如果您将它与无符号值一起使用,它可能会打印出实际值以外的内容。使用"%u" 查看实际值,或使用%x 以十六进制查看。

在声明中

unsigned int x = -1;

表达式-1 是int 类型,其值为-1。初始化程序将此值从 int 转换为 unsigned int。有符号到无符号转换的规则表明该值以UINT_MAX + 1 为模减少,因此-1 将转换为UINT_MAX(如果unsigned int 是32 位,则可能是0xffffffff4294967295)。

您只是不能将负值分配给无符号类型的对象。任何此类值在分配之前都会转换为无符号类型,结果将始终 >= 0。

【讨论】:

  • 但是基思,那么,0x FF FF FF FF 的 MSB 为 1,用于表示负数,对吧?那么,通过将负值赋给 unsigned int 类型的变量,我们真正得到了什么?
  • @n0nChun:这不是表示负数的唯一方式。 2's-complement 是最常用的方法;其他是 1s'-complement 和 sign-and-magnitude (这三个都是 C 标准允许的)。关键是您确实不能将负值分配给无符号整数;任何负值都将被隐式转换,从而产生一个非负无符号值。此外,unsigned int 不一定是 32 位;它可以小到 16 位。 -1 将始终转换为 UINT_MAX,不一定是 0xffffffff
  • @n0nChun MSB 不用于表示无符号整数中的负数。如果你使用%u,你会看到 2 * 0x7fffffff。无符号整数的最大值是 2 倍。
  • @Daniel:2 倍大加 1
  • @keith 感谢您的更正。因为不需要 +/- 0,所以负数比正数多一个。每个负数都映射到一个无符号数,这就是 +1 的来源。
【解决方案2】:

发生的事情是您首先将值转换为无符号整数,将 0xffffffff 分配给 x。然后使用 printf("%d\n") 将值转换回带符号的 int 仍然保持 0xffffffff 的值。因此打印-1。

【讨论】:

  • 关闭,但不完全。他转换,而不是转换值(转换是隐式的,不是通过转换运算符完成的)。并且printf 调用不执行类型转换;相反,它可能将无符号值的表示解释为好像它是有符号值(类型双关语)。 (严格来说,printf 调用的行为是未定义的。)
  • 是的,你是对的,我用错了词。查看 gcc 的 asm 输出将显示两个 mov,导致只是对值的解释。
【解决方案3】:

使用%u 而不是%d 以打印无符号值。然后你应该会看到 0xFFFFFFFF。

【讨论】:

  • 我知道但没有回答我的问题
  • 将 -1 分配给 unsigned int 不仅会删除符号位 (0x7FF...),它仍将是 0xFF...,请使用 printf("%1$u : 0x%1$X\n", x); 自己查看。跨度>
  • x = -1x = 0xFFFFFFFF 应该产生相同的结果。 x = 0x7FFFFFFF 是一个不同的值,您不会从上述任何分配中得到它。如果这仍然不能澄清它,那么我不确定你还在问什么......
  • 忘记你有一个无符号整数,把它想象成内存中的一个空间。当您将变量分配给 -1 时,您真正的意思是将带符号的 int -1 的值存储到内存中的这个空间。然后使用 printf,%d 要求它从内存中的该空间读取一个带符号的 int。这两个都是一致的,所以你会得到一个-1。您在内存中的空间可以是任何类型的变量,您仍然会看到“-1”。
  • @asc99c - 虽然您的 printf '%d' 解释是正确的,但您的任务却不是。 C99 规范实际上为此指定了行为,它不仅仅是简单的内存分配。 2) 否则,如果新类型是无符号的,则在新类型可以表示的最大值的基础上反复加减一,直到该值在新类型的范围内。
猜你喜欢
  • 1970-01-01
  • 2017-05-07
  • 1970-01-01
  • 2014-08-02
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
相关资源
最近更新 更多