C++无符号和有符号转换

我以前见过这种问题,但提供的答案并没有让我明白一切。发布此问题时,通常会附上下一个示例:

#include <iostream>

int main()
{
    unsigned int u = 10;
             int i = -42;

    std::cout << i + i << std::endl;
    std::cout << i + u << std::endl;

    return 0;
}

输出:

-84
4294967264

所有按预期工作 int 转换为无符号。但是,如果 的绝对值i小于 ,u则似乎没有发生这种转换。

#include <iostream>

int main()
{
    unsigned int u = 10;
             int i = -3;

    std::cout << i + i << std::endl;
    std::cout << i + u << std::endl;

    return 0;
}

输出:

-6
7

我没有看到任何提到它的答案,也找不到任何解释。尽管这似乎是合乎逻辑的事情发生,但我对此没有任何解释。

回答

后:

unsigned int u = 10;
         int i = -3;

i + u收益的评估首先转换iunsigned int。对于 32 位unsigned int,此转换包含模 2 32,即 4,294,967,296。这种包装的结果是?3 + 4,294,967,296 = 4,294,967,293。

转换后,我们将添加 4,294,967,293(已转换i)和 10 ( u)。这将是 4,294,967,303。由于这超出了 32 位 的范围unsigned int,因此它以 4,294,967,296 为模包装。结果是 4,294,967,303 ?4,294,967,296 = 7。

因此打印“7”。


回答

但是如果 i 的绝对值小于 u,则似乎没有发生这种转换。

你的假设是错误的:这种转换正在发生。“这种转换”是指当 -3 转换为无符号类型时,结果是 4'294'967'293。

我没有看到任何提到它的答案,也找不到任何解释。

无符号算术是模块化的。这就是模算术的工作原理。

要理解模算术,请考虑 12 小时制的工作原理。它也是模块化的。您会注意到钟面没有任何负数:

  • 时间是 10 点(今天上午)。3 小时前,现在几点了?那是 7 点(今天上午)。
  • 时间是 10 点(今天上午)。42 小时前,现在几点了?4点(前天下午)

无符号算术的工作原理正是如此。除了在 32 位类型的情况下有 4'294'967'296 个值而不是 12 个值。


为了将不可表示的值转换为可表示的范围,只需添加或减去模数(时钟情况下为 12,32 位无符号整数情况下为 4'294'967'296),直到该值处于可表示范围内。

以下是时钟示例的数学计算:

R ? 10 + (-3)          (mod 12)
// -3 = 9  + (12 * -1)
R ? 10 + 9             (mod 12) 
R ? 19                 (mod 12)
// 19 = 7  + (12 *  1)
R ? 7                  (mod 12)

R ? 10 + (-42)         (mod 12)
// -42 = 6 + (12 * -4)
R ? 10 + 6             (mod 12)
R ? 16                 (mod 12)
// 16 = 4 +  (12 *  1)
R ? 4                  (mod 12)

以下是您的示例的数学计算:

R ? 10 + (-42)         (mod 4'294'967'296)
// -42           = 4'294'967'254 + (4'294'967'296 * -1)
R ? 10 + 4'294'967'254 (mod 4'294'967'296)
R ? 4'294'967'264      (mod 4'294'967'296)

R ? 10 + (-3)          (mod 4'294'967'296)
// -3            = 4'294'967'293 + (4'294'967'296 * -1)
R ? 10 + 4'294'967'293 (mod 4'294'967'296)
R ? 4'294'967'303      (mod 4'294'967'296)
// 4'294'967'303 = 7             + (4'294'967'296 * -1)
R ? 7                  (mod 4'294'967'296)


以上是C++无符号和有符号转换的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>