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

时间:2019-03-01 15:15:13

标签: c++ language-lawyer signed twos-complement c++20

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

那么,有符号到无符号的转换是什么意思,反之亦然?我查看了cppreference,发现以下内容:

  

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

     

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

不幸的是,我在理解此措词时遇到困难,我想知道C ++ 20工作草案中写的是什么。

所以有两个问题:

  1. 语言律师部分:有人可以指出该标准的确切含义以及该标准在何处注明吗?

  2. 有人可以用更多的外行术语来解释该措辞,也许还可以解释模块化算术并提供示例?

2 个答案:

答案 0 :(得分:4)

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

  

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

其中范围指数在[basic.fundamental]的表中进行了描述,但表示您期望的含义(int至少为16,long long至少为64,依此类推)

例如,将值short的{​​{1}}转换为-3就是要找到类型unsigned short的唯一值,该值与unsigned short模{ {1}} ...也就是说-3216。但是将216-3的相同65533值转换为short会将模数基数更改为-3,因此最终得到的是unsigned long long

从带符号类型转换为具有不同范围指数的带符号类型(或类似地从无符号到无符号)更简单-您可以将位砍掉或零扩展。例如,将值258的264转换为18446744073709551613shortint只是258,而转换为long则是2。

答案 1 :(得分:1)

您的报价中使用了很多单词来表达一些简单的内容:对于每个整数i,在k0之间恰好有一个整数M,因此{ {1}}(在数学意义上,不是“固定大小整数表示形式”的意义)。用更多的外行术语来说,i % M == k的意思是“如果我从i % M == k加上或减去M正确的次数,我可以获得i”。

对于整数转换,k,其中M = 2^N是目标类型中的位数。该标准说:

  

[conv.integral]#3

     

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

在示例中:

说您的目标类型有4位,因此它可以表示N2^4 = 16的{​​{1}}值。将0转换为该范围会产生151会产生114会产生1415会产生{{1} },15产生160产生17,依此类推。转换1会产生182会产生00会产生-1等。

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