我正在阅读Why is the sum of two large integers a negative number in the C language?。然后我尝试了以下代码:
int main() {
unsigned int x,y,s;
x = 4294967295;
y = 4294967295;
s = x+y;
printf("%u",s);
return 0;
}
输出:4294967294
1)如何计算总和?我对链接中的解释感到有点困惑。
当我将x
和y
的值增加到超出unsigned int
范围的范围时,结果似乎总是在unsigned int的范围内。事实上,似乎结果不断下降。
它确实给出了以下错误。
sample.c:7:9:警告:大整数隐式截断为无符号类型[-Woverflow]
2)我是否可以强制执行此程序,以便只要x
和y
的值超过unsigned int range程序就会抛出错误。
答案 0 :(得分:2)
C标准对无符号整数溢出有明确定义的行为。当发生这种情况时,数学结果将以最大允许值+ 1为模数进行截断。在外行人的术语中,这意味着值会回绕。
如果添加4294967295和4294967295,则此环绕行为将导致4294967294。
投掷错误将违反标准。
答案 1 :(得分:1)
1)如何计算总和?
请参阅@dbush好的答案。
2)我可以强制执行此程序,以便只要x和y的值超过unsigned int range程序就会抛出错误。
代码可以使用unsigned
数学轻松检测数学溢出。如果sum小于加法的操作数,则会发生数学溢出。只针对x
或y
中的一个进行测试就足够了。
unsigned int x,y,s;
x = 4294967295;
y = 4294967295;
s = x+y;
printf("%u\n",s);
if (s < x) puts("Math overflow");
// or
if (s < y) puts("Math overflow");
return 0;
对于已签名的 int
测试,请参阅Test if arithmetic operation will cause undefined behavior
答案 2 :(得分:0)
在你的情况下unsigned int
是32位,4294967295 + 4294967295 == 8589934590,其中 33 位二进制值:
1 1111 1111 1111 1111 1111 1111 1111 1110
^
Carry bit
进位位丢失,因为表示只有32位,结果值为:
1111 1111 1111 1111 1111 1111 1111 1110 = 4294967294 decimal
您必须先检测溢出,然后才能将结果存储在更大的类型中并测试其值。
if( UINT_MAX - x < y )
{
puts("Math overflow") ;
}
else
{
s = x + y ;
printf( "%u\n", s ) ;
}
或者:
unsigned long long s = x + y ;
if( s > UINT_MAX )
{
puts("Math overflow") ;
}
else
{
printf( "%u\n", (unsigned int)s ) ;
}
答案 3 :(得分:0)
大多数现代计算机以8位为单位存储内存,称为&#34;字节&#34; (也称为&#34; octet&#34;)。可以在这样的计算机中进行算术运算 字节,但通常在更大的单位中完成,称为&#34;(短) 整数&#34; (16位),&#34;长整数&#34; (32位)或&#34;双整数&#34; (64位)。短整数可用于存储0到0之间的数字 2 16 - 1,或65,535。 长整数可用于存储数字 0和2 32 - 1,或4,294,967,295。和双整数可用于 存储0到2之间的数字 64 - 1,或18,446,744,073,709,551,615。 (检查这些!)
[...]
当计算机执行无符号整数算术运算时, 可能会出现三种可能的问题:
如果结果太大而无法分配到指定的位数 它,&#34;溢出&#34;据说已经发生。例如,如果结果 使用16位整数的操作大于65,535,a 溢出结果。
在两个整数的划分中,如果结果本身不是一个 整数,a&#34;截断&#34;据说已经发生过:10分为3分 截断为3,额外的1/3丢失。这不是问题 当然,如果程序员的意图是忽略其余部分!
任何除零都是错误,因为除零不是 可能在算术的背景下。
[删除原始重点;重点补充。]