关于
FLT_ROUNDS
中声明的 <float.h>
宏,C 标准中的脚注指出:
浮点加法的舍入模式由实现定义的 FLT_ROUNDS 值来表征:23)
-1 不确定
0 走向零
1 到最接近的
2 朝向正无穷
3 朝向负无穷
23) 对
的评估可以通过FLT_ROUNDS
中的函数fesetround
正确反映舍入模式的任何执行时间变化。<fenv.h>
用一个小示例程序尝试一下:
#include <float.h>
#include <fenv.h>
#include <stdio.h>
#pragma STDC FENV_ACCESS ON
int main()
{
printf( "Initial FLT_ROUND: %d\n", FLT_ROUNDS );
printf( "Initial fegetround: %d\n\n", fegetround() );
fesetround( FE_TOWARDZERO );
printf( "Current FLT_ROUND: %d\n", FLT_ROUNDS );
printf( "Current fegetround: %d\n", fegetround() );
}
编译:
gcc -std=c11 testme.c -o testme -lm
我在 Linux 上得到以下输出:
Initial FLT_ROUND: 1
Initial fegetround: 0
Current FLT_ROUND: 1
Current fegetround: 3072
在 Cygwin 上:
Initial FLT_ROUND: 1
Initial fegetround: 0
Current FLT_ROUND: 1
Current fegetround: 3
鉴于标准的声明,我会期待:
...
Current FLT_ROUND: 0
...
这是不合格的实现,还是我错误地理解了标准脚注?
FWIW,在 Android / Termux 上尝试同样的操作给了我:
Initial FLT_ROUND: 1
Initial fegetround: 0
Current FLT_ROUND: 0
Current fegetround: 3
这让我怀疑 Linux 和 Cygwin 上的实现都有错误......?
GCC 将此记录为“实现定义的行为”:
以 FLT_ROUNDS 的非标准值为特征的舍入行为(C90、C99 和 C11 5.2.4.2.2)。
GCC does not use such values.
Termux 使用 BSD libc 和 clang“伪装”为 GCC,这解释了 Android 上符合标准的行为。