4

在下面的代码中,我0xffffffff将(32 位)乘以 2unsigned int并将其存储在unsigned long long(64 位)中。为什么我没有得到实际的输出是8589934588. 相反,我得到4294967294. 提前致谢。输出:sizeof i=4 Sizeof 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;
}
4

3 回答 3

5

这是因为i*2是整数乘法。即使您将其存储在 a 中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
于 2013-07-31T20:05:07.503 回答
3

i*2对它被分配给 an 的事实一无所知unsigned long long- 因为iis anunsigned int并且2is anint乘法是使用unsigned int类型执行的,这会产生你得到的结果。

您可以通过制作文字来解决问题,2该文字促进乘法,或者在乘法之前强制转换,具有相同的效果:unsigned long longiunsigned long longiunsigned long long

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

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

于 2013-07-31T20:05:40.423 回答
2

因为iis an unsigned intand 2is an intand will bepromote to unsigned intthe operation will just wrap around。一种解决方案是强制i转换为unsigned long long

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

C11 标准草案的相关部分位于6.2.5/9

涉及无符号操作数的计算永远不会溢出,因为无法由结果无符号整数类型表示的结果会以比结果类型可以表示的最大值大一的数字为模减少。

于 2013-07-31T20:10:19.927 回答