我想知道当问题中的整数类型无法准确表示该值时,从C中的浮点类型转换为无符号整数类型会发生什么。举个例子
func (void)
{
float a = 1E10;
unsigned b = a;
}
我在系统上获得的b
的值(系统上的unsigned
可以表示从0到2 32-1的值)是1410065408
。这对我来说似乎很明智,因为它只是转换结果的最低位。
我相信此类操作的行为未由标准定义。我错了吗?如果我做这样的事情,我在实践中会有什么期望?
而且,带符号类型会发生什么?如果b
的类型为int
,则得到-2147483648
,这对我来说真的没有意义。
[当值溢出时将浮点类型转换为无符号整数类型会发生什么?
未定义行为(UB)
另外@user694733很好的答案,为防止由于float
到unsigned
代码范围超出引起的不确定行为,可以先测试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
}
pedantic代码将采取其他步骤来应对罕见的FLT_RADIX 10
。
[FLT_EVAL_METHOD
,允许以更高的精度计算float
,可能会起作用,但到目前为止,我还没有看到它对上述解决方案产生负面影响。
在两种情况下,值都超出范围,所以它是不确定的行为。
6.3.1.4实数浮点数和整数
- [将实数浮点型的有限值转换为
_Bool
以外的整数类型时,小数部分将被舍弃(即该值被截断为零)。如果值整数部分不能用整数类型表示,其行为是不确定的。 61)61)将整数类型的值转换为无符号类型时执行的余数运算当实数浮点型的值转换为无符号型时,不需要执行。就这样可移植实际浮点值的范围是(−1,U type _ MAX + 1)。
为了进行良好定义的代码,在进行转换之前,应检查值是否在可能的范围内。