【问题标题】:Casting a negative int to a bigger unsigned int in C在 C 中将负整数转换为更大的无符号整数
【发布时间】:2021-04-10 16:41:12
【问题描述】:
int main(){
 int a = -33553454;
 unsigned long b = a;
 return 0;
}

在上面的例子中,a 是第一个符号扩展为 64 位值的 signed 整数(意味着 1 将放在其左侧),然后将值分配给 b 作为无符号整数。

可以肯定地说,只有原始源操作数的类型很重要(如果它有符号或无符号),并且在这种情况下不考虑目标类型(因为目标是无符号的,你会认为@987654325 @ 不会得到符号扩展,因为最终结果无论如何都是无符号的,并且 0 将填充 b 的左侧。)

【问题讨论】:

  • 你编译过这个警告吗?
  • 我不确定你的意思是什么“在这种情况下不考虑目标类型”
  • 您首先描述的是二进制补码表示法的工作原理。
  • 我的意思是目的地是无符号的,你会认为 a 不会得到符号扩展,因为最终结果无论如何都是无符号的,而 0 将填充 b 的左侧。

标签: c


【解决方案1】:

您正在将 int 值转换为 unsigned long 值。这是如何发生的由C standard 的第 6.3.1.3 节规定:

1 当一个整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新的表示 类型,它是不变的。

2 否则,如果新类型是无符号的,则通过重复加减一的方式转换值 新类型可以表示的最大值 直到值在新类型的范围内。

3 否则,新类型是有符号的,值不能在其中表示;结果是实现定义的 或引发实现定义的信号

第 2 段适用于这种情况。因为所讨论的值是负数,因此超出了unsigned long 的范围,所以该类型的最大值 +1 会被添加到原始值中以获得新值。

因此,假设unsigned long的最大值为2 64 sup> -1(或1844674407370955161616151615)转换为18446744073709551616-33553454 = 18446744073675998162(0xFFFFFFFFFE0003D2)。您会注意到,如果您的机器使用二进制补码表示(大多数都这样做),那么这些数字的表示恰好是相同的(在符号扩展之后)。

【讨论】:

  • 非常感谢这个例子,让它更清楚了。不确定是谁编写了这些 C 文档,他们无法以更令人困惑的方式对其进行解释。
  • 他们可以只是符号扩展源值,然后将结果分配给无符号结果值,这样解释起来会更简单吗?这就像在做unsigned int a = -12,-12 被签名扩展为 int 然后结果被分配给a
  • 语言规范是为编译器编写者编写的,而不是普通程序员。
  • @RobertHarvey:好的语言规范是为了精确而编写的(受其他目标的限制),这是编译器编写者和优秀程序员都需要的。
  • @EricPostpischil:当然,但是用一种语言编写程序不像编写编译器那样需要规范,而且众所周知,语言规范对程序员不友好。
猜你喜欢
  • 1970-01-01
  • 2012-08-13
  • 2012-01-09
  • 1970-01-01
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多