2013-07-31 301 views
3

在下面的代码中,我将0xffffffff乘以unsigned int(32位),并将其存储在unsigned long long(64位)中。为什么我没有得到8589934588的实际输出。相反,我得到4294967294。 在此先感谢。 OUTPUT: SIZEOF i = 4的 的sizeof J = 8 2xi = 4294967292unsigned int(32bit)为无符号long long(64bit)

/* Code starts here */ 
#include <stdio.h> 
#include <stdlib.h> 

int main (void) 
{ 
    unsigned int i=4294967294; 
    unsigned long long j=i*2; 
    printf("Sizeof i=%d\n", sizeof(i)); 
    printf("Sizeof J=%d\n", sizeof(j)); 
    printf("2xi=%llu\n", j); 

    return 0; 
} 

回答

5

这是因为i*2是整数乘法。即使你将它存储在一个long long,你仍然在做整数运算,这会导致溢出。

下面的代码工作,因为我们推动它高达long long

#include <stdio.h> 
#include <stdlib.h> 
int main (void) 
{ 
    unsigned int i=4294967294; 
    unsigned long long j=((unsigned long long)i)*2; 
    printf("Sizeof i=%d\n", sizeof(i)); 
    printf("Sizeof J=%d\n", sizeof(j)); 
    printf("2xi=%llu\n", j); 

    return 0; 
} 

结果:

bash-4.1$ gcc long.c 
bash-4.1$ ./a.out 
Sizeof i=4 
Sizeof J=8 
2xi=8589934588 
+2

请记住'signed overflow'是未定义的行为,但是无符号的溢出只是包装。 –

3

i*2一无所知的事实,它被分配到一个unsigned long long - 因为iunsigned int2int乘法是使用unsigned int类型执行的,其产生t他结果你得到了。

您可以通过2解决问题的unsigned long long文字,促进iunsigned long long为乘法,或铸造iunsigned long long乘法之前,它具有相同的效果:

unsigned long long j=i*2ULL; 
/* or */ 
unsigned long long j=((unsigned long long)i)*2; 

一般来说,请记住:在C中,赋值/初始化的目标不影响如何计算右边的表达式 - 涉及的类型仅由操作数的类型决定。

2

由于iunsigned int2int,将被晋升为unsigned int操作只会环绕。一个解决办法是投iunsigned long long

unsigned long long j = ((unsigned long long)i)*2 ; 

draft C11 standard相关的部分是6.2.5/9

涉及无符号的操作数A计算可以永远不会溢出, 因为结果不能代表通过得到的无符号整数类型是 减少的模数是比由最终类型表示的最大值可以是 大的数。