【问题标题】:does in c++ the conversion from unsigned int to int always preserve the bit pattern?在 c++ 中,从 unsigned int 到 int 的转换总是保留位模式吗?
【发布时间】:2013-01-17 20:42:57
【问题描述】:

从标准 (4.7) 看来,从 int 到 unsigned int 的转换,当它们都使用相同的位数时,纯粹是概念性的:

如果目标类型是无符号的,则结果值是最小的 与源整数一致的无符号整数(模 2 n 其中 n 是用于表示无符号类型的位数)。 [注:在 二进制补码表示,这种转换是概念性的,并且 位模式没有变化(如果没有截断)。 — 尾注]

所以在这个方向上,转换会保留位掩码。我不确定标准是否保证从 unsigned int 到 int 的转换相同(再次假设使用相同的位数)。这里的标准说:

如果目标类型是有符号的,如果可以,则值不变 以目标类型(和位域宽度)表示;否则, 该值是实现定义的。

这里的“目标类型”到底是什么意思?例如 2^32-1 不能用 32 位整数表示。这是否意味着它不能在目标类型中表示,因此不能假设位模式将保持不变?

【问题讨论】:

  • 理论上您可以是一个互补系统,并且位模式可能会改变。这将是 C++ 标准之外的东西。但实际上,是否有任何非二进制补码系统了?

标签: c++ casting language-lawyer


【解决方案1】:

int 在这种情况下是目标类型。正如您所说,2^32-1 在这种情况下无法表示,因此它是特定于实现的。虽然,我只见过它保留位模式。

编辑:我应该补充一点,在嵌入式世界中,当一个存储位置需要多个位对位相同的表示时,我们经常使用联合。

在这种情况下

union FOO {
    int32_t signedVal;
    uint32_t unsignedVal;
} var;

var 可以作为 var.signedVal 访问,以获取存储为有符号整数的 32 位,var.unsignedVal 以获取存储为无符号值的 32 位。在这种情况下,位将被保留。

【讨论】:

    【解决方案2】:

    你不能假设任何事情

    第一个引号没有说明位掩码保持不变。它可能在二进制补码中相同,但在一个补码或其他表示中不同。

    第二,实现定义的意思是实现定义的,你不能假设任何东西。

    理论上,每次转换后表示可以完全不同。就是这样。


    如果您以现实的方式看待它,事情就会变得更加具体。通常,int 存储在二进制补码中,signed->unsigned 保留与 unsigned->signed 一样的模式(因为值可以由实现定义,最便宜的方法是什么都不做)。

    【讨论】:

    • (假设二进制补码表示法)第一个引号确实表明位掩码保持不变。它说,事实上,正是如此。 Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). 换句话说,如果你转换为相同大小的无符号整数类型,位模式将完全相同。
    【解决方案3】:

    “目标类型”是指您分配/转换到的类型。

    整个段落意味着转换为 32 位 signed int 的 32 位 unsigned int 将保持原样,前提是该值适合 signed int。如果它们不适合,则取决于其作用的实现(例如截断)。这意味着它实际上取决于位是保留还是更改(无法保证)。

    或者换句话说:如果unsigned int 使用它的最高有效位,则结果不再是可预测的。否则没有任何变化(除了改变“盒子上的名字”)。

    【讨论】:

    • 我相信上面的分析假设没有填充位并且值位在相同的位置。
    • 我会说它不会改变任何东西(只要您假设两种类型的填充位相同)。如果这不是真的,那么无论如何,您实际上是在看不同的长度(除非我误解了您)。
    猜你喜欢
    • 1970-01-01
    • 2014-04-05
    • 2013-09-03
    • 2016-07-09
    • 2012-05-06
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 2012-04-28
    相关资源
    最近更新 更多