【问题标题】:Can an unsigned long become negative when multiplied by a float?unsigned long 乘以浮点数会变成负数吗?
【发布时间】:2015-02-12 10:13:53
【问题描述】:

标题可能选错了,但我找不到这个问题的一个好的单行摘要。我的问题是我无法理解我的编译器在做什么,我想知道我是否在编译器中发现了一个错误......或者我对 C 语言的理解。

我的理解是:

  • - 1UL == ULONG_MAX,这是安全的,因为无符号数的溢出行为是明确定义的
  • 产品(- 1UL) * 1.0f 涉及将左操作数转换为浮点数,并且此转换保留值(即ULONG_MAX),但舍入错误除外

到目前为止,我的编译器都同意,除非 1UL 来自变量。这是我的测试程序,其输出为 cmets:

#include <stdio.h>

int main(void)
{
    unsigned long one = 1;
    unsigned long minus_one = - one;
    printf("%lu\n", - one);            // 18446744073709551615
    printf("%g\n", minus_one * 1.0f);  // 1.84467e+19
    printf("%g\n", (- one) * 1.0);     // 1.84467e+19
    printf("%g\n", (- 1UL) * 1.0f);    // 1.84467e+19
    printf("%g\n", (- one) * 1.0f);    // -1
    return 0;
}

我无法理解最后的输出。我尝试了各种优化级别和各种语言标准(C90、C99 和 C11),结果相同。有人知道吗?

环境:gcc 4.8.1 / Ubuntu Linux 14.04 / x86-64 (I32LP64)

编辑:我刚刚注意到我的问题可能与combination of unary minus and float conversion 重复。

【问题讨论】:

  • 该程序在 Visual Studio 和我的 VM(Ubuntu 10.04,gcc 4.4.3)中给出了预期的输出。

标签: c implicit-conversion


【解决方案1】:

这似乎是 gcc 4.8 中的一个错误。我在 4.8 中的行为与您相同,但 gcc 4.9 和 clang 显示了更正的行为。

【讨论】:

  • 你能确认这是一个错误吗?我可能是 UB,在这种情况下,即使 4.8 也是“正确”
  • @user694733:就在你引用的下一段中:如果要转换的值在可以表示但不能精确表示的值范围内,则结果是以实现定义的方式选择的最接近的较高或最近较低的可表示值。
  • 这似乎是正确的。如果long 在该平台上是 32 位的,float 应该有足够的范围,在这种情况下排除 UB。
  • long 是 64 位的,但仍在 float 的范围内。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-26
  • 2023-03-05
  • 1970-01-01
  • 2012-05-24
相关资源
最近更新 更多