相同的FLT_EVAL_METHOD,GCC/Clang中的结果不同

ano*_*nol 7 c floating-point gcc clang

当使用GCC(4.8.2)和Clang(3.5.1)编译时,以下程序(从此处改编)给出不一致的结果.特别是,GCC结果即使在何时FLT_EVAL_METHOD也不会改变.

#include <stdio.h>
#include <float.h>

int r1;
double ten = 10.0;

int main(int c, char **v) {
  printf("FLT_EVAL_METHOD = %d\n", FLT_EVAL_METHOD);
  r1 = 0.1 == (1.0 / ten);
  printf("0.1 = %a, 1.0/ten = %a\n", 0.1, 1.0 / ten);
  printf("r1=%d\n", r1);
}
Run Code Online (Sandbox Code Playgroud)

测试:

$ gcc -std=c99 t.c && ./a.out
FLT_EVAL_METHOD = 0
0.1 = 0x1.999999999999ap-4, 1.0/ten = 0x1.999999999999ap-4
r1=1

$ gcc -std=c99 -mpfmath=387 t.c && ./a.out
FLT_EVAL_METHOD = 2
0.1 = 0x0.0000000000001p-1022, 1.0/ten = 0x0p+0
r1=1

$ clang -std=c99 t.c && ./a.out
FLT_EVAL_METHOD = 0
0.1 = 0x1.999999999999ap-4, 1.0/ten = 0x1.999999999999ap-4
r1=1

$ clang -std=c99 -mfpmath=387 -mno-sse t.c && ./a.out
FLT_EVAL_METHOD = 2
0.1 = 0x0.07fff00000001p-1022, 1.0/ten = 0x0p+0
r1=0
Run Code Online (Sandbox Code Playgroud)

请注意,根据这篇博文,GCC 4.4.3用于在第二次测试中输出0而不是1.

一个可能相关的问题表明在GCC 4.6中已经纠正了一个错误,这可能解释了为什么GCC的结果不同.

我想确认这些结果是否不正确,或者是否有一些微妙的评估步骤(例如新的预处理器优化)可以证明这些编译器之间的差异.

Pas*_*uoq 6

这个答案是关于在你走得更远之前你应该解决的问题,因为它会对更难发生的事情做出推理:

当然打印0.1 = 0x0.07fff00000001p-10220.1 = 0x0.0000000000001p-1022只能是编译平台上的错误,因为ABI在使用时不匹配-mfpmath=387.过多的精度都不能解释这些值中的任何一个.

您可以尝试在测试文件中包含您自己的转换为可读格式,以便也可以编译该转换-mfpmath=387.或者在另一个文件中创建一个小存根,不使用该选项编译,使用简约调用约定:

在其他文件中:

double d;
void print_double(void)
{
  printf("%a", d);
}
Run Code Online (Sandbox Code Playgroud)

在编译的文件中-mfpmath=387:

extern double d;
d = 0.1;
print_double();
Run Code Online (Sandbox Code Playgroud)