在有符号和无符号之间进行隐式转换的c ++代码安全性

时间:2018-11-06 22:39:20

标签: c++

根据herehere中讨论的有符号和无符号整数类型之间的隐式转换规则,将unsigned intint求和时,有符号{{ 1}}首先转换为int

考虑以下示例最小程序

unsigned int

尽管如此,程序的输出仍为预期的1:#include <iostream> int main() { unsigned int n = 2; int x = -1; std::cout << n + x << std::endl; return 0; } 首先转换为x,并且unsigned int的总和导致整数溢出,给出“正确”的答案。

在与上一个代码类似的代码中,如果我确定n是肯定的,我是否可以假设n + xunsigned int n的和给出期望值?

2 个答案:

答案 0 :(得分:5)

  

在与上一个代码类似的代码中,如果我确定n + x为正,我可以假定unsigned int n和int x的总和是否为预期值?

是的

首先,使用模算术将有符号值converted设置为无符号:

  

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(取模2 n    其中n是用来表示无符号类型的位数。

然后,两个无符号值将使用模算法为added

  

无符号整数应服从2 n 的算术定律,其中n是该特定整数大小的值表示形式中的位数。

这意味着您将获得预期的答案。

即使在数学意义上结果为负,在C ++中的结果也将是与负数取模的数字。

请注意,我在这里假设您要添加两个相同大小的整数。

答案 1 :(得分:1)

我想您可以确定,并且它不是实现定义的,尽管对于不使用二进制补码表示负值的系统,该声明需要对标准进行一些解释。

首先,让我们说明清楚的事情:无符号积分不会溢出,而是取2 ^ nrOfBits值的模(参见online C++ standard draft):

  

6.7.1基本类型

     

(7)无符号整数应服从2n模算术定律   其中n是该值的表示形式中的位数   整数的特定大小。

所以这只是一个负值nv是否正确转换为无符号整数位模式nv(conv)的问题,这样x + nv(conv)始终与x - nv相同。对于使用二进制补码的系统而言,事情很清楚,因为实际上对二进制补码进行了设计,以使该算法立即起作用。

对于使用其他负值表示形式的系统,我们必须仔细阅读标准:

  

7.8整体转化

     

(2)如果目标类型是无符号的,则结果值为   等于源整数的最小无符号整数(取模2n   其中n是用于表示无符号类型的位数。 [   注意:以两位数的补码表示,此转换为   概念上的,并且位模式没有变化(如果有的话)   不能断档)。 —endnote]

正如脚注明确指出的那样,在二进制补码表示中,位模式没有变化,我们可以假设在2s补码以外的系统中,会发生 real 转换, x + nv(conv) == x - nv

因此,由于7.8(2),我想说您的假设是正确的。