【问题标题】:Does signed to unsigned casting in C changes the bit valuesC中的有符号到无符号转换是否会更改位值
【发布时间】:2020-02-13 09:06:44
【问题描述】:

我已经做了一些快速测试,在 C 中将 signed int 转换为 unsigned int 不会更改位值(在在线调试器上)。

我想知道的是它是由 C 标准保证还是只是常见(但不是 100% 确定)行为?

【问题讨论】:

  • 它改变了context,即值的含义。所有计算机数据都由一组有限的数字组成,这些数字在上下文中具有意义。但是,当将int 转换为float 时,表示会发生变化,这会有所不同。
  • 只有赋值才会改变值。从有符号(2s-补码)转换为无符号是不安全的转换,我认为是特定于实现的。
  • @LegendofPedro 使用两个已知为非负数的 int 值是安全的,并且您希望它们的总和没有 int 溢出的危险。
  • @WeatherVane(和 LegendofPedro):演员阵容定义完美,没有溢出的危险,无论签署 int 的符号如何。

标签: c casting integer


【解决方案1】:

signed intunsigned int 的转换不会改变最常见的two’s-complement C implementations 中的位表示,但会改变负数的位表示,包括可能的负零在一个补码符号和幅度系统上。

这是因为转换(unsigned int) a定义为保留位,但结果是a 除以UINT_MAX + 1正余数(或正如 C 标准(C11 6.3.1.3p2) 所说,

在新类型可以表示的最大值的基础上反复加减一,直到值在新类型的范围内。

负数的二进制补码表示是有符号数最常用的表示正是因为它具有负值n 映射到与数学值@987654329 相同的位模式的属性@ - 它使得有符号和无符号加法可以使用相同的机器指令,并且由于回绕,负数将起作用。

【讨论】:

    【解决方案2】:

    从有符号整数转换为无符号整数需要生成正确的算术结果(相同的数字),无符号整数的大小,可以这么说。也就是之后

    int i = anything;
    unsigned int u = (unsigned int)i;
    

    在具有 32 位整数的机器上,要求是 u 等于 i,模 232

    (我们也可以尝试说u 接收到值i % 0x100000000,但事实证明这不太正确,因为 C 规则说当你将一个负整数除以一个正整数时,你会得到一个商四舍五入到 0 和一个负余数,这不是我们想要的那种模数。)

    如果i 为0 或正数,不难看出u 将具有相同的位模式。 如果i 是负数,并且如果您在 2 的补码机器上,结果也保证结果具有相同的位模式。 (我很想在这里提供一个很好的结果证明,但我现在没有时间尝试构建它。)

    当今绝大多数机器都使用 2 的补码。但是,如果您使用的是 1 的补码或符号/幅度机器,我很确定位模式不会总是相同。

    因此,归根结底,位模式的相同性由 C 标准保证,而是由于 C 标准的要求和 2 的补码算法的特殊性的结合而产生的。

    【讨论】:

    • 您应该用二进制补码 C 实现,而不是二进制补码 machine 来表达规则。虽然 C 通常旨在使用与其目标处理器匹配的功能,但实现具有最终发言权。如果我编写一个带有反码的 C 实现来支持我想在计算机博物馆展示的一些古老软件,即使底层机器是二进制补码,它也会遵守反码规则。
    • @EricPostpischil 你知道现有的补充机器吗?
    • @GuillaumePetitjean:正如我刚才所说,C 可以通过软件而不是硬件来实现。因此,底层机器不是决定因素。因此,任何特定类型的机器的存在都是无关紧要的。 C 标准中规定的规则很明确:行为由 C 实现定义,而不是由硬件定义。
    • 我完全理解@EricPostpischil。但我想在实践中,在 2 的补码机器上选择 1 的补码 C 实现是没有意义的。只是好奇。
    • @GuillaumePetitjean:说明 C 整数的行为由机器决定是 false。说明 C 整数的行为是由 C 实现决定的 true。就是这么简单。一个是真的,一个是假的,教学生虚假陈述是不好的,依靠虚假陈述有时会导致意想不到的错误。 C 编译器在优化方面变得越来越积极,利用 C 标准中的规则,即使它们不是目标硬件的直接结果。没有理由在这里做出错误的陈述。
    猜你喜欢
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 2011-04-19
    相关资源
    最近更新 更多