【问题标题】:Casting signed to unsigned and vise versa while widening the byte count将有符号转换为无符号,反之亦然,同时扩大字节数
【发布时间】:2020-02-24 01:27:45
【问题描述】:
uint32_t a = -1;            // 11111111111111111111111111111111
int64_t b = (int64_t) a;    // 0000000000000000000000000000000011111111111111111111111111111111

int32_t c = -1;             // 11111111111111111111111111111111
int64_t d = (int64_t) c;    // 1111111111111111111111111111111111111111111111111111111111111111

从上面的观察来看,似乎只有原始值的sign 很重要。 即,如果原始 32 位数字是无符号的,则将其转换为 64 位值将在其左侧添加 0's,无论目标值是有符号还是无符号,并且;

如果原始 32 位数字是有符号的且为负数,则将其转换为 64 位值将在其左侧添加 1's,无论目标值是有符号还是无符号。

以上说法正确吗?

【问题讨论】:

  • 对于您展示的具体示例,您所看到的只是值没有变化。在第一种情况下,4294967295 保持 4294967295,在第二种情况下 -1 保持 -1。
  • 是的,我不是在谈论值本身,而是在谈论它的符号扩展。
  • 由于值没有改变,它不是关于 C 的属性,而是关于无符号和 2 的补码表示的属性。对于无符号值,是的,前面会添加零。对于有符号值,是的,将发生符号扩展。当表示很重要时,固定宽度的整数非常方便。 究竟是什么意思?
  • 不,事实并非如此。对于给出的特定示例,从固定宽度的 32 位整数到 int64_t 事情的行为就像您描述的那样。一旦您离开固定宽度类型的领域,签名表示就是实现定义的。此外,类型的宽度也很重要。您必须参考Usual arithmetic conversions 以了解这些值会发生什么。从那里,了解表示可以让您确定二进制结果。
  • @paxdiablo 从签名到未签名,我认为您所说的是正确的。问题是 Jeff 对二进制表示的许多陈述并不总是正确的。

标签: c sign-extension


【解决方案1】:

正确,是源操作数决定了这一点。

uint32_t a = -1;
int64_t b = (int64_t) a;

这里没有符号扩展,因为源值是一个无符号uint32_t。符号扩展的基本思想是确保更广泛的变量具有相同的值(包括符号)。来自无符号整数类型,该值始终为正。下面的标准 sn-p /1 涵盖了这一点。

负号扩展(即二进制补码值的最高 1 位被复制到更宽类型中的所有高位(a))仅在 时发生有符号的 类型在宽度上有所扩展,因为只有有符号的类型可以是负数。


如果原始 32 位数字是有符号且为负数,则将其转换为 64 位值将在其左侧添加 1,而不管目标值是有符号还是无符号。

下面的标准 sn-p /2 涵盖了这一点。在扩展位时您仍然必须保持值的符号,但将负值(假设源为负)推入无符号变量只会数学上MAX_VAL + 1 添加到值直到它在目标类型的范围内(实际上,对于二进制补码,不做加法,只是以不同的方式解释相同的位模式)。


标准中涵盖了这两种情况,在本例中为C11 6.3.1.3 Signed and unsigned integers /1/2

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

2/否则,如果新类型是无符号的,则在新类型可以表示的最大值的基础上重复加减1,直到值在新类型的范围内。

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

请注意,上述前两点涵盖了您的扩大转化。我已经将第三点包括在内,因为它涵盖了从uint32_tint32_tunsigned intlong 的转换,它们具有相同的宽度(它们都有一个最小范围 em> 但不要求unsigned intlong“薄”)。


(a)这可能在一个的补码或符号大小表示上有所不同,但由于它们正在被删除,所以没有人真正关心那么多。

见:

了解更多详情。

在任何情况下,固定宽度类型二进制补码,因此您不必担心示例代码的这一方面。

【讨论】:

  • 谢谢,我的陈述不是说同样的话吗?我稍微修改了一下。
  • @Jeff,是的,我最初将您的问题读作“这是如何工作的?”而不是“它是否以这种方式工作?”,希望现在已经修复。答案基本上证实了你的怀疑,参考控制它的标准部分。
  • 我的问题下还有另一条评论说该语句不正确,仅适用于固定数据类型。那是关于什么的?
  • @Jeff,我相信您所指的报价是 signed representations are implementation-defined - 这是因为二进制补码只是负数的三种可能表示形式中的 一个(目前- 正在进行更改以删除其他两个)。但是,我认为这不会影响符号扩展的结果,只会影响实现它的方法。
  • 我明白了,是的,我只关心 2 的补码。自从sign extending a signed number add's 1's to it's left only if its negative 之后,我也没有修改我的第二个语句
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-08
  • 2011-08-09
  • 2011-10-14
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多