在C ++ 20中从有符号整数转换为无符号整数,反之亦然

问题描述 投票:3回答:2

在C ++之前,20个有符号整数不能保证是两个补码。现在我们有两篇论文提出将两个补码的标准化作为唯一的表示:p0907p1236,如果我理解正确的话,其中一个被合并到C ++ 20工作草案中。

那么,签名到无符号转换是什么意思,反之亦然?我看了cppreference并找到了以下措辞:

如果目标类型是无符号的,则结果值是最小的无符号值,等于源值modulo 2n,其中n是用于表示目标类型的位数。

如果目标类型已签名,则如果源整数可以在目标类型中表示,则值不会更改。否则,结果是目标类型的唯一值等于源模块2n,其中n是用于表示目标类型的位数。 (注意,这与有符号整数算术溢出不同,后者是未定义的)。

不幸的是,我在理解这个措辞时遇到了问题,我想知道C ++ 20 Working Draft中的内容。

所以有两个问题:

  1. 语言律师部分:有人可以指出标准准确说明的内容以及标准中所说的内容吗?
  2. 有人可以用更多外行人的术语来解释这个措辞,可能还解释模数运算并提供例子吗?
c++ language-lawyer signed twos-complement c++20
2个回答
4
投票

转换规则是[conv.integral]/3

否则,结果是目标类型的唯一值,该值与源整数模2N一致,其中N是目标类型的范围指数。

范围指数在[basic.fundamental]的表中描述,但意味着你所期望的(对于int,它至少为16,对于long long,它至少为64,等等)。

例如,将值为short-3转换为unsigned short,就是找到unsigned short类型的唯一值,它与-3 modulo 216一致...也就是说,216-365533。但是将short的相同-3值转换为unsigned long long会将模数基数改为264,所以你最终会使用18446744073709551613

从带符号的类型转换为具有不同范围指数的带符号类型(或者同样无符号到无符号)更直接 - 您可以只切断位或对它们进行零扩展。将值为258的short转换为intlonglong long仅为258,但例如signed char为2。


1
投票

你的引语使用了很多单词来说一些非常简单的东西:对于每个整数ik0之间只有一个整数M,因此i % M == k(在数学意义上,不是“固定大小整数表示”意义)。在更多的外行人看来,i % M == k的意思是“如果我从M增加或减少i正确的次数,我可以获得k”。

在积分转换的情况下,M = 2^N其中N是目标类型中的位数。标准说:

[conv.integral]#3

否则,结果是目标类型的唯一值,该值与源整数模2^N一致,其中N是目标类型的范围指数。

在示例中:

假设您的目的地类型有4位,因此它可以表示从2^4 = 16015值。将1转换为此范围产生114产量1415产量1516产量017产量118产量2等。转换0产量0-1产量15-2产量14等。

如果您真的想要更深入地介绍模块化算法,那么这超出了本网站的范围。您应该参考网络上的大量资源,例如this one

© www.soinside.com 2019 - 2024. All rights reserved.