根据here和here中讨论的有符号和无符号整数类型之间的隐式转换规则,将unsigned int
与int
求和时,有符号{{ 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 + x
和unsigned int n
的和给出期望值?>
答案 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),我想说您的假设是正确的。