在使用 Berkeley TestFloat 时,我注意到浮点到整数转换的测试是通过检查(特别是)特定结果值来完成的:
// file: test_a_f32_z_i32_rx.c
// function: test_a_f32_z_i32_rx
...
if ( (trueZ != subjZ) || (trueFlags != subjFlags) ) {
if (
verCases_checkInvInts
|| (trueFlags != softfloat_flag_invalid)
|| (subjFlags != softfloat_flag_invalid)
|| ((subjZ != 0x7FFFFFFF) && (subjZ != -0x7FFFFFFF - 1)
&& (! f32_isNaN( genCases_f32_a ) || (subjZ != 0)))
) {
++verCases_errorCount;
这里我们看到具体的结果值:
0
、0x7FFFFFFF
(最大有符号整数)、-0x7FFFFFFF - 1
(最小有符号整数)。
但是,根据 C11(及更高版本)标准,将超出范围的浮点数转换为整数会导致 UB。由于通常
(int)f
会导致硬件指令的生成(例如x86_64的cvttss2si
),我想知道:是否有任何硬件可以将超出范围的浮点转换为非零/最小/最大整数?
从 C11 开始,C 标准将超出范围的浮点值转换为整数视为未定义行为 (UB)。这意味着编译器不受特定行为的约束,旨在防止跨平台问题。虽然某些硬件可能会以独特的方式处理此类转换,但这并不是标准化或通用的。 Berkeley TestFloat 框架使用特定值进行测试来测试是否符合标准,但这些可能无法反映所有硬件行为。优先考虑可移植性,遵循 C 标准的规则并避免对硬件行为的假设。显式处理超出范围的情况或使用 isfinite 等库函数来确保转换前定义明确的行为。