【发布时间】:2022-01-04 00:00:17
【问题描述】:
示例代码(t0.c):
#include <stdio.h> // fix for clang, see https://stackoverflow.com/q/69976945/1778275
#if __STDC_IEC_559__ == 1
#pragma message "__STDC_IEC_559__ is 1"
#else
#pragma message "__STDC_IEC_559__ is not 1"
#endif
调用:
# gcc 11.2 on Linux on x86-64
$ gcc t0.c -std=c11 -pedantic -Wall -Wextra -fno-rounding-math
t0.c:3:9: note: '#pragma message: __STDC_IEC_559__ is 1'
# clang 13.0.0 on Linux on x86-64
$ clang t0.c -std=c11 -pedantic -Wall -Wextra -ffp-model=fast
t0.c:3:9: warning: __STDC_IEC_559__ is 1 [-W#pragma-messages]
# icc 2021.1.2 on Linux on x86-64
$ icc t0.c -std=c11 -pedantic -Wall -Wextra -fp-model=fast
__STDC_IEC_559__ is 1
这里我们看到非严格浮点模型不会改变1 的值__STDC_IEC_559__。为什么?
UPD20211126: 回复:
开关本身不会改变舍入行为,因此不会改变是否定义了宏。
现在-fno-rounding-math下的gcc错误编译了以下程序(t1.c):
#include <stdio.h>
#include <float.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON
int main(void)
{
#if __STDC_IEC_559__ == 1
if (fesetround(FE_UPWARD) == 0)
{
printf("%a\n", FLT_MIN / 1.0000001f);
}
#endif
return 0;
}
调用和执行:
# gcc 11.2 on Linux on x86-64
gcc t1.c -std=c11 -pedantic -Wall -Wextra -lm -fno-rounding-math && ./a.out
t1.c:5: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
0x1.fffffcp-127
# gcc 11.2 on Linux on x86-64
gcc t1.c -std=c11 -pedantic -Wall -Wextra -lm -frounding-math && ./a.out
t1.c:5: warning: ignoring '#pragma STDC FENV_ACCESS' [-Wunknown-pragmas]
0x1p-126
在这里我们看到__STDC_IEC_559__ == 1 下的结果是不同的。出乎意料。
注意:是的,在 gcc 中 Pragma STDC * (C99 FP) unimplemented。
UPD20211130。出于好奇:如果这些在非严格浮点模型下的实现不符合附件 F 中的规范,那么他们定义__STDC_IEC_559__ 到1 的目的是什么?
【问题讨论】:
-
但是,我认为
-ffp开关不会改变浮点的表示形式——它们仍然是 IEE754(= ISO/IEC/IEEE 60559)格式。 -
人类编写的软件不正确。
-
阅读手册。 -frounding-math ...应该为动态改变FP舍入模式的程序指定该选项。
-
@n.1.8e9-where's-my-sharem。来自comments:每个单独的开关组合与编译器都被视为不同的 C 实现。
标签: c gcc clang icc standards-compliance