C ++乘法256 * 256 * 256 * 256 = 0?积分常数溢出C4307

时间:2017-06-15 05:37:40

标签: c++

有人可以解释为什么以下代码总共为0? 这如何加起来为零?我使用不同的类型获得相同的结果,例如long和long long。谢谢!

int num;
num = (256 * 256 * 256 * 256)-1;    //-1 warning C4307: '*': integral constant overflow
cout << num << endl;

num = 256 * 256 * 256 * 256;    //0 warning C4307: '*': integral constant overflow
cout << num << endl;            

num = (256 * 256) * (256 * 256);     //0 warning C4307: '*': integral constant overflow
cout << num << endl;


num = (256 * (256 * 256) * 256);     //0 warning C4307: '*': integral constant overflow
cout << num << endl;             

num = 256 * 256 * 256; // 16777216
cout << num << endl;

num = 256 * 256;    //65536
cout << num << endl;

输出:
-1
0
0
0
16777216个
65536

更改类型仅影响: num = 256 * 256; num = num * 256 * 256; 加起来正确。

long long num;
num = (256L * 256L * 256L * 256L)-1;        //warning C4307: '*': integral constant overflow
cout << num << endl;

num = (256L * 256L * 256L * 256L);      //warning C4307: '*': integral constant overflow
cout << num << endl;            

num = (256 * 256) * (256 * 256);     //warning C4307: '*': integral constant overflow
cout << num << endl;


num = (256 * (256 * 256) * 256);     //warning C4307: '*': integral constant overflow
cout << num << endl;             

num = 256 * 256 * 256;
cout << num << endl;

num = 256 * 256;
cout << num << endl;
num = num * 256 * 256;
cout << num << endl;

cout << sizeof(int) << endl;
cout << sizeof(long long) << endl;

输出:
-1
0
0
0
16777216个
65536个
4294967296个
sizeof(int)4
sizeof(long long)8

我想这与&#39; *&#39;的数量有关。乘法运算符。数学运算3或更少。

4 个答案:

答案 0 :(得分:2)

即使目标变量是long long,表达式的所有部分都是(32位)int。无论你如何尝试对乘法进行分组,结果都是2 ** 32,其低32位为0.

答案 1 :(得分:2)

256 = 2 8

256 * 256 * 256 * 256

= 2 8 * 2 8 * 2 8 * 2 8

= 2 (8 + 8 + 8 + 8)

= 2 32

然而(根据您的错误),您的机器支持int s在-2 31 到2 31 - 1范围内。

所以2 32 导致溢出,导致0,因为除了MSB之外的所有位都是0。

答案 2 :(得分:2)

  

为什么warning C4307: '*': integral constant overflow

文字256的默认大小为4个字节,涉及4个字节整数的算术运算结果将被分配为 4个字节 。所以:

256 in hex notation is 0x100
256 * 256 * 256 * 256
= 0x100 * 0x100 * 0x100 * 0x100
= 0x 01 00 00 00 00  //Too big for 4 bytes, therefore overflow
  

为什么256 * 256 * 256 * 256 == 0

从上面继续。

//The result of the calculation is **mashed** into 4 bytes
0x 01 00 00 00 00
      ^^^^^^^^^^^
//The last 4 bytes == 0 and this is the value assigned to num

此时num被声明为8字节整数(long long):

  • 0 是结果 (以4个字节为单位)。
  • 0将分配到num

解决方案

将您的文字声明为 8字节值(即256LL),计算结果也应为8个字节。

long long num = 256LL * 256LL * 256LL * 256LL;

注意:原始类型的大小限制是软件开发中的标准问题。如果使用8字节整数,则仍然限制为最大可能的8字节值,即2 64 -1。有关详细信息,请阅读有关整数类型here的部分。

如果您需要任意大数字,则需要使用提供此类功能的库。

答案 3 :(得分:2)

我们的号码系统(我们写的)以十进制(基数10)存储数字,其中每个数字可以采用10个不同的值(0-9)。如果你有一个只有6位数的计算器,你可以显示的最大数字是999999.如果你尝试乘以1000 * 1000你会得到一个错误,或者计算器必须摆脱6位以上的数字或两者兼而有之。 / p>

计算机以二进制(基数2)存储数字。 C(和C ++)定义了几个data types,用于定义数字的存储方式。 Microsoft C++ (VCPP) further clarifies these。对于有符号整数,它们是:

  • short(最小16位)MSVCPP = 16位
  • int(最小16位)MSVCPP = 32位
  • long(最小32位)MSVCPP = 32位
  • long long(最小64位)MSVCPP = 64位

    请注意“&#39;通常&#39;因为C标准设定了最小尺寸但不是最大尺寸

    另请注意:我知道我跳过了char,因为(恕我直言)它有点混合型。

还有一些无符号类型用于交换符号位以获得额外的数字,因此它们可以存储更大(正)的数字。

好的,回到你的问题。 由于@Coldspeed提到256 = 2 8 。在二进制中,需要10位表示有符号数,9位表示无符号。这很容易适合任何这些类型。当你得到256 * 256 * 256 * 256 = 2 32 时,这将需要34位,只适合long long。就像在6位数计算器上一样,您将得到松散高位数或两者都错误的错误。在这种情况下,丢失高位数将导致&#39; 0&#39;。

这解释了你的前四个答案(第一个,认为0-1 = -1)

但为什么没有long long工作。答案是,这只是存储最终结果的地方。除非另有说明,否则所有整数文字(数字)都将被视为int类型;因此,在将数字放入num之前计算中的计算期间发生截断/错误。

最后两个在C&#39; C&#39;因为它们可能会导致错误,因为结果大于short可以容纳,int不能保证大于short;但是,对于MSVCPP,它是(32位)。