【问题标题】:warning C4307: '*' : integral constant overflow警告 C4307:“*”:整数常量溢出
【发布时间】:2017-05-05 08:50:12
【问题描述】:

我在下编程时遇到了一件奇怪的事情。这是关于 32bit 加法 signed 数字

(uint32)(SIN32_MIN * (-1)) //signed integer 4 bytes

给:

warning C4307: '*' : integral constant overflow

SIN32_MIN = -2147483648

【问题讨论】:

  • signed numbers(uint32)......o.O
  • SIN32_MIN = -2147483648
  • 未定义的行为

标签: c++ c++


【解决方案1】:

如果将INT32_MIN 乘以-1,则会出现溢出,因为 2147483648 不能用带符号的 32 位整数表示。

如果您想获得 -1 * (-2147483648) = 2147483648,请尝试这样做:(((uint32_t)(INT32_MAX)) + 1)

Sample code:

#include <stdint.h>
#include <stdio.h>

int main()
{
    uint32_t n = static_cast<uint32_t>(INT32_MAX)+1;
    printf("n: %u\n", n);
}

输出:

n: 2147483648

这会产生no warnings with clang

作为一个侧节点,通常 INT32_MIN 不定义为 #define INT32_MIN -2147483648 出于类似的原因。它通常被定义为(-2147483647 - 1) 或类似的东西。

你也可以do this instead:(uint32_t)(INT32_MIN * -1LL)

【讨论】:

  • (((uint32_t)(INT32_MAX)) + 1);相同的错误编译器抛出
  • @user3231318 你确定吗?你检查sample code了吗?
  • @Pavel 实际上 IDEOne 即使发生溢出也不会发出警告。 ideone.com/VMAVB2
【解决方案2】:

在整数为2's complement(几乎是任何现代通用计算机)的环境中,可以用固定位数表示的数字范围不是关于 0 对称的。在 32 位数字中,最大的可以表示的正数是2147483647,是二进制的

0111 1111 1111 1111 1111 1111 1111 1111

数字 -2147483648 * -1 是 2147483648 与 2147483647 + 1 相同,但是当我们将其加 1 时,位模式为

1000 0000 0000 0000 0000 0000 0000 0000

设置了最高位,这意味着它是负数的表示。实际上是-2147483648。 +2147483648 不能用 32 位表示。

【讨论】:

    【解决方案3】:

    公式SIN32_MIN * (-1) 结果为2147483648 超出signed int32 范围:

    –2147483648 to 2147483647
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-06
      • 2011-11-07
      • 2019-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      相关资源
      最近更新 更多