在下面的代码中,我将0xffffffff
乘以unsigned int
(32位),并将其存储在unsigned long long
(64位)中。为什么我得不到8589934588
的实际输出。相反,我得到4294967294
。
提前致谢。
OUTPUT:
sizeof i = 4
尺寸J = 8
2xi = 4294967292
/* 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;
}
答案 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
答案 1 :(得分:3)
i*2
对于将unsigned long long
分配给i
的事实一无所知 - 因为unsigned int
是2
而int
是unsigned int
乘法是使用2
类型执行的,这会产生你得到的结果。
您可以通过unsigned long long
i
字面值来解决问题,将unsigned long long
提升为i
进行乘法,或将unsigned long long
强制转换为{{ 1}}在乘法之前,它具有相同的效果:
unsigned long long j=i*2ULL;
/* or */
unsigned long long j=((unsigned long long)i)*2;
一般来说,请记住:在C中,赋值/初始化的目标不影响如何计算右边的表达式 - 所涉及的类型仅由操作数的类型决定。
答案 2 :(得分:2)
由于i
是unsigned int
且2
是int
,并且会被提升为unsigned int
,因此操作将会回滚。一种解决方案是将i
投射到unsigned long long
:
unsigned long long j = ((unsigned long long)i)*2 ;
draft C11 standard的相关部分位于6.2.5/9
:
涉及无符号操作数的计算永远不会溢出, 因为无法用结果无符号整数类型表示的结果是 减少模数可以是最大值的数字 由结果类型表示。