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

标签 c gcc floating-point clang

以下程序(改编自 here)在使用 GCC (4.8.2) 和 Clang (3.5.1) 编译时给出不一致的结果。特别是,即使 FLT_EVAL_METHOD 发生变化,GCC 结果也不会发生变化。

#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);
}

测试:

$ 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

请注意,根据 this blog post , GCC 4.4.3 在第二次测试中用于输出 0 而不是 1。

A possibly related question表明 GCC 4.6 中的错误已得到纠正,这可能解释了为什么 GCC 的结果不同。

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

最佳答案

这个答案是关于你在继续之前应该解决的问题,因为它会让你更难推理否则会发生什么:

确定打印0.1 = 0x0.07fff00000001p-10220.1 = 0x0.0000000000001p-1022使用 -mfpmath=387 时,只能是 ABI 不匹配导致的编译平台错误.这些值都不能以过度精确为借口。

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

在其他文件中:

double d;
void print_double(void)
{
  printf("%a", d);
}

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

extern double d;
d = 0.1;
print_double();

关于c - 相同的 FLT_EVAL_METHOD,GCC/Clang 中的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28851350/

相关文章:

c - float变量不满足条件(C)

algorithm - 定点 Cholesky 算法的优点

c++ - C++ 中 `double` 的 Java 样式打印

c - block 模式下的读取中断

c - GCC 的 -Wmaybe-uninitialized 是否为基于枚举的 switch 语句生成带有 -O1 的虚假警告?

c - 全局静态和局部静态在何时何地存储和初始化?

c - 臂组件 memset 更换

gcc - 编译FFMPEG教程程序

c - 如何使用c中的标记来计算出现次数

C Socket - 确定数据长度