【问题标题】:Overflow after an implicit cast隐式转换后溢出
【发布时间】:2015-11-26 23:33:22
【问题描述】:

当我尝试从 double 到 unsigned long 进行隐式强制转换时,出现溢出警告:“警告:隐式常量转换中的溢出 [-Woverflow]”。

说明如下:

unsigned long ulongMax = pow(2.0, 64.0) - 1; 

但是当我像下面这样明确地投射时,没关系!

unsigned long ulongMax = (unsigned long) (pow(2.0, 64.0) - 1);

我不明白为什么我会收到警告,结果 (18446744073709551615) 与标题“limits.h”中的ULONG_MAX 相同。

【问题讨论】:

  • 您的问题应该包含确切的警告信息,并且最好确认 ulong 的大小,例如printf("%lu\n", ULONG_MAX);
  • 我已经包含了警告信息。在我的系统(Arch linux 64bits)上,ULONG_MAX 值为 18446744073709551615,正如我所说。

标签: c casting double integer-overflow


【解决方案1】:

pow(2.0, 64.0) 返回一个double

但是(假设是普通的 IEEE754 系统),pow(2.0, 64.0)pow(2.0, 64.0) - 1 的值实际上是相等的。这是因为我们超出了在double 中可以精确表示相邻整数的范围。 (当然,一个 64 位的 double 不能代表所有的 64 位整数)。

现在,从浮点到整数类型的超出范围强制转换会导致 undefined behaviour,无需诊断。

您的编译器试图通过在第一种情况下警告您有关此未定义行为来提供帮助,但(大概)它将添加演员表视为您说“我不想听到此警告”的消息.

【讨论】:

  • 在我看来,double 表示为 int,但是是的,你是对的。所以 double 内整数的最大值应该是 2^52 -1。谢谢。
【解决方案2】:

警告意味着如果pow(2.0, 64.0) - 1 太大或带有小数部分(比如 1.7*10^308,这是双精度数的最大值)或 0.9,它可能会丢失精度,这将被截断为 0)。

使用显式转换 (unsigned long) (pow(2.0, 64.0) - 1) 时您没有收到警告的原因是,您明确地说“我实际上想从这个双精度中得到一个无符号长整数(不管它有什么讨厌的后果)”

【讨论】:

    【解决方案3】:

    您收到警告的最可能原因是您平台上的 unsigned long 的大小是 32 位,而不是 64 位。

    如果您切换到 64 位无符号,警告将消失:

    unsigned long long ulongMax = pow(2.0, 64.0) - 1; 
    printf("%llu", ulongMax);
    

    Demo.

    显式转换消除了警告,因为它本质上告诉编译器您知道正在发生的事情,并且您希望它保持安静并按您说的做。

    【讨论】:

      猜你喜欢
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-10
      • 1970-01-01
      • 1970-01-01
      • 2018-12-01
      • 2010-09-08
      相关资源
      最近更新 更多