【问题标题】:What happens when casting floating point types to unsigned integer types when the value would overflow?当值溢出时将浮点类型转换为无符号整数类型会发生什么?
【发布时间】:2018-04-06 07:58:12
【问题描述】:

我想知道在 C 中从浮点类型转换为无符号整数类型时会发生什么情况,而该值不能由所讨论的整数类型准确表示。举个例子

func (void)
{
float a = 1E10;
unsigned b = a;
}

我在我的系统上获得的b 的值(我的系统上的unsigned 能够表示从0 到232-1 的值)是1410065408。这对我来说似乎是明智的,因为它只是转换结果的最低位。

我相信标准未定义此类操作的行为。我错了吗?如果我做这样的事情,我在实践中可以期待什么?

另外,有符号类型会发生什么?如果bint 类型,我会得到-2147483648,这对我来说真的没有意义。

【问题讨论】:

  • 准确地说,这不是强制转换。赋值导致隐式转换
  • 强制转换和隐式转换之间有什么区别会影响这种情况下的结果吗?
  • 强制转换是一种强制转换操作,它会导致显式转换。相同的规则用于隐式和显式转换,但它们在标准中是不同的。
  • 你可以得到-2147483648,因为这是你的处理器的指令产生的,或者你可以在不同的处理器上得到别的东西,或者你会得到奇怪的结果,因为你的处理器使用的是 64-位有符号转换指令在源代码中实现什么是 32 位无符号转换。作为未定义的行为,编译器不必保持一致。见blog.frama-c.com/index.php?post/2013/10/09/…

标签: c casting floating-point overflow unsigned


【解决方案1】:

将浮点类型转换为无符号整数类型时值溢出时会发生什么 (?)

未定义的行为 (UB)


另外@user694733很好的回答,为了防止未定义的行为导致floatunsigned的代码超出范围可以先测试float的值。

然而,对于无符号类型,尤其是有符号类型,测试范围很棘手。细节是整数转换之前的所有转换和常量必须精确。接近极限的 FP 数学也需要精确。

例子:

转换为 32 位无符号数的有效范围为 -0.999... 到 4294967295.999...。

转换为带符号的 32 位 2 的补码在 -2147483648.999... 到 2147483647.999...的范围内有效。


// code uses FP constants that are exact powers-of-2 to insure their exact encoding.

// Form a FP constant that is exactly UINT_MAX + 1
#define FLT_UINT_MAX_P1 ((UINT_MAX/2 + 1)*2.0f)

bool convert_float_to_unsigned(unsigned *u, float f) {
  if (f > -1.0f && f < FLT_UINT_MAX_P1) {
    *u = (unsigned) f;
    return true;
  }
  return false;  // out of range
}


#define FLT_INT_MAX_P1 ((INT_MAX/2 + 1)*2.0f)
bool convert_float_to_int(int *i, float f) {
  #if INT_MIN == -INT_MAX
  // Rare non 2's complement integer
  if (fabsf(f) < FLT_INT_MAX_P1) {
    *i = (int) f;
    return true;
  }
  #else
  // Do not use f + 1 > INT_MIN as it may incur rounding
  // Do not use f > INT_MIN - 1.0f as it may incur rounding
  // f - INT_MIN is expected to be exact for values near the limit
  if (f - INT_MIN > -1 && f < FLT_INT_MAX_P1) {
    *i = (int) f;
    return true;
  }
  #endif 
  return false;  // out of range
}

迂腐的代码会采取额外的步骤来应对罕见的FLT_RADIX 10

FLT_EVAL_METHOD,它允许以更高的精度计算 float 数学,可能会起作用,但到目前为止,我认为它不会对上述解决方案产生负面影响。

【讨论】:

    【解决方案2】:

    在这两种情况下,值都超出范围,因此这是未定义的行为。

    6.3.1.4 实数浮点数和整数

    1. 当实浮点类型的有限值转换为_Bool以外的整数类型时, 小数部分被丢弃(即,该值被截断为零)。如果值 整数部分不能用整数类型表示,行为未定义。 61)

    61) 将整数类型的值转换为无符号类型时执行的求余运算 将实浮点类型的值转换为无符号类型时不需要执行。就这样 可移植实浮点值的范围是 (−1, Utype_MAX+1)。

    要制作这个定义明确的代码,您应该在进行转换之前检查值是否在可能的范围内。

    【讨论】:

      猜你喜欢
      • 2011-01-03
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多