在c奇怪的行为中添加两个数字

时间:2017-10-13 17:07:02

标签: c add

我正在阅读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)如何计算总和?我对链接中的解释感到有点困惑。

当我将xy的值增加到超出unsigned int范围的范围时,结果似乎总是在unsigned int的范围内。事实上,似乎结果不断下降。
它确实给出了以下错误。

  

sample.c:7:9:警告:大整数隐式截断为无符号类型[-Woverflow]

2)我是否可以强制执行此程序,以便只要xy的值超过unsigned int range程序就会抛出错误。

4 个答案:

答案 0 :(得分:2)

C标准对无符号整数溢出有明确定义的行为。当发生这种情况时,数学结果将以最大允许值+ 1为模数进行截断。在外行人的术语中,这意味着值会回绕。

如果添加4294967295和4294967295,则此环绕行为将导致4294967294。

投掷错误将违反标准。

答案 1 :(得分:1)

  

1)如何计算总和?

请参阅@dbush好的答案。

  

2)我可以强制执行此程序,以便只要x和y的值超过unsigned int range程序就会抛出错误。

代码可以使用unsigned数学轻松检测数学溢出。如果sum小于加法的操作数,则会发生数学溢出。只针对xy中的一个进行测试就足够了。

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)

根据kias.dyndns.org

  

大多数现代计算机以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丢失。这不是问题   当然,如果程序员的意图是忽略其余部分!

  •   
  • 任何除零都是错误,因为除零不是   可能在算术的背景下。

  •   

[删除原始重点;重点补充。]