在C ++之前,20个有符号整数不能保证是两个补码。现在我们有两篇论文提出将两个补码的标准化作为唯一的表示:p0907和p1236,如果我理解正确的话,其中一个被合并到C ++ 20工作草案中。
那么,签名到无符号转换是什么意思,反之亦然?我看了cppreference并找到了以下措辞:
如果目标类型是无符号的,则结果值是最小的无符号值,等于源值modulo
2n
,其中n
是用于表示目标类型的位数。如果目标类型已签名,则如果源整数可以在目标类型中表示,则值不会更改。否则,结果是目标类型的唯一值等于源模块
2n
,其中n
是用于表示目标类型的位数。 (注意,这与有符号整数算术溢出不同,后者是未定义的)。
不幸的是,我在理解这个措辞时遇到了问题,我想知道C ++ 20 Working Draft中的内容。
所以有两个问题:
转换规则是[conv.integral]/3:
否则,结果是目标类型的唯一值,该值与源整数模
2N
一致,其中N
是目标类型的范围指数。
范围指数在[basic.fundamental]的表中描述,但意味着你所期望的(对于int
,它至少为16,对于long long
,它至少为64,等等)。
例如,将值为short
的-3
转换为unsigned short
,就是找到unsigned short
类型的唯一值,它与-3
modulo 216
一致...也就是说,216-3
或65533
。但是将short
的相同-3
值转换为unsigned long long
会将模数基数改为264
,所以你最终会使用18446744073709551613
。
从带符号的类型转换为具有不同范围指数的带符号类型(或者同样无符号到无符号)更直接 - 您可以只切断位或对它们进行零扩展。将值为258的short
转换为int
或long
或long long
仅为258,但例如signed char
为2。
你的引语使用了很多单词来说一些非常简单的东西:对于每个整数i
,k
和0
之间只有一个整数M
,因此i % M == k
(在数学意义上,不是“固定大小整数表示”意义)。在更多的外行人看来,i % M == k
的意思是“如果我从M
增加或减少i
正确的次数,我可以获得k
”。
在积分转换的情况下,M = 2^N
其中N
是目标类型中的位数。标准说:
否则,结果是目标类型的唯一值,该值与源整数模
2^N
一致,其中N
是目标类型的范围指数。
在示例中:
假设您的目的地类型有4位,因此它可以表示从2^4 = 16
到0
的15
值。将1
转换为此范围产生1
,14
产量14
,15
产量15
,16
产量0
,17
产量1
,18
产量2
等。转换0
产量0
,-1
产量15
,-2
产量14
等。
如果您真的想要更深入地介绍模块化算法,那么这超出了本网站的范围。您应该参考网络上的大量资源,例如this one。