C当值溢出时,将浮点类型转换为无符号整数类型时会发生什么

时间:2017-10-25 09:32:18

标签: c casting floating-point unsigned

我想知道在C中从浮点类型转换为无符号整数类型时会发生什么情况,而这个值无法用相关的整数类型准确表示。举个例子

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

我在我的系统上b的值(我的系统上的unsigned能够表示0到2 ^ 32-1之间的值)是1410065408。这对我来说似乎是明智的,因为它只是演员结果的最低位。

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

此外,签名类型会发生什么?如果b的类型为int,我会收到-2147483648,这对我来说并不合理。

2 个答案:

答案 0 :(得分:2)

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

  

6.3.1.4实数浮点数和整数

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

    61)当整数类型的值转换为无符号类型时执行的剩余操作   当实际浮动类型的值转换为无符号类型时,不需要执行。就这样   便携式实数浮点值的范围是(-1,U 类型 _MAX + 1)。

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

答案 1 :(得分:2)

  

当值溢出(?)

时,将浮点类型转换为无符号整数类型时会发生什么

未定义的行为(UB)

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

然而,对于无符号类型,特别是对于签名类型,测试范围是棘手的。细节是整数转换之前的所有转换和常量必须 exact 。接近极限的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数学,可能会起作用,但到目前为止,我认为它不会对上述解决方案产生负面影响。