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

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

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

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

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

此外,签名类型会发生什么? 如果bint类型,我得到-2147483648 ,这对我来说没有意义。

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

未定义的行为 (UB)


另外@ user694733很好的答案,防止超出范围float引起的未定义行为unsigned代码可以先测试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数学,可能起作用,但到目前为止,我没有看到它对上述解决方案产生负面影响。

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

6.3.1.4实数浮点数和整数

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

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

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