我想计算两个 IEEE 754 binary64 数字的总和,四舍五入。为此,我编写了下面的 C99 程序:
#include <stdio.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
int main(int c, char *v[]){
fesetround(FE_UPWARD);
printf("%a\n", 0x1.0p0 + 0x1.0p-80);
}
但是,如果我使用各种编译器编译和运行我的程序:
$ gcc -v
…
gcc 版本 4.2.1(Apple Inc. build 5664)
$ gcc -Wall -std=c99 add.c && ./a.out
add.c:3:警告:忽略#pragma STDC FENV_ACCESS
0x1p+0
$ 铿锵 -v
苹果 clang 版本 1.5 (tags/Apple/clang-60)
目标:x86_64-apple-darwin10
线程模型:posix
$ clang -Wall -std=c99 add.c && ./a.out
add.c:3:14:警告:不支持编译指示 STDC FENV_ACCESS ON,忽略
pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS ON
^
生成 1 个警告。
0x1p+0
它不起作用!(我期待结果0x1.0000000000001p0)。
实际上,计算是在编译时以默认的舍入到最近模式完成的:
$ clang -Wall -std=c99 -S add.c && cat add.s
add.c:3:14:警告:不支持编译指示 STDC FENV_ACCESS ON,忽略
pragma [-Wunknown-pragmas]
#pragma STDC FENV_ACCESS ON
^
生成 1 个警告。
…
LCPI1_0:
.quad 4607182418800017408
…
callq _fesetround
移动 $1, %cl
movsd LCPI1_0(%rip), %xmm0
leaq L_.str(%rip), %rdx
movq %rdx, %rdi
移动 %cl, %al
callq _printf
…
L_.str:
.asciz "%a\n"
是的,我确实看到了每个编译器发出的警告。我知道在生产线的规模上打开或关闭适用的优化可能很棘手。如果可能的话,我仍然希望以文件的比例关闭它们,这足以解决我的问题。
我的问题是:我应该在 GCC 或 Clang 中使用什么命令行选项来编译包含旨在以 FPU 舍入模式而不是默认模式执行的代码的 C99 编译单元?
题外话
在研究这个问题时,我发现了这个GCC C99 合规性页面,其中包含以下条目,我将离开这里以防其他人觉得它很有趣。呸呸呸。
浮点数 | | 环境访问 | 不适用 | 库功能,无需编译器支持。 在 <fenv.h> | |