为什么非严格浮点模型不改变 __STDC_IEC_559__ 的值 1?
Why don't non-strict floating-point models change the value 1 of __STDC_IEC_559__?
示例代码(t0.c):
#include <stdio.h> // fix for clang, see
#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
这里我们看到非严格浮点模型不会改变__STDC_IEC_559__
的值1
。为什么?
UPD20211126:
回复:
The switch itself does not change the rounding behaviour, and thus does not change whether the macro is defined.
现在 -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
?
的目的是什么?
-fno-rounding-math
是 gcc 默认值。它启用 假定 无舍入 IEEE 算法的优化。 -frounding-math
关闭这些优化。开关本身不会改变舍入行为,因此不会改变是否定义了宏。
-frounding-math
Disable transformations and optimizations that assume default
floating-point rounding behavior. This is round-to-zero for all
floating point to integer conversions, and round-to-nearest for all
other arithmetic truncations. This option should be specified for
programs that change the FP rounding mode dynamically, or that may
be executed with a non-default rounding mode. This option disables
constant folding of floating-point expressions at compile time
(which may be affected by rounding mode) and arithmetic
transformations that are unsafe in the presence of sign-dependent
rounding modes.
-ffast-math
在 gcc 中关闭宏。它不会在 clang 中这样做,这可能是一个错误。
因为他们好像有bug。
UPD.
- 将
__STDC_IEC_559__
定义为1
以防不符合附件F中的规范不是错误。
- 通常非严格的浮点模型意味着不符合附件 F 中的规范。如果是这样,则不清楚
__STDC_IEC_559__
定义为 1
的目的。
示例代码(t0.c):
#include <stdio.h> // fix for clang, see
#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
这里我们看到非严格浮点模型不会改变__STDC_IEC_559__
的值1
。为什么?
UPD20211126: 回复:
The switch itself does not change the rounding behaviour, and thus does not change whether the macro is defined.
现在 -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
?
-fno-rounding-math
是 gcc 默认值。它启用 假定 无舍入 IEEE 算法的优化。 -frounding-math
关闭这些优化。开关本身不会改变舍入行为,因此不会改变是否定义了宏。
-frounding-math
Disable transformations and optimizations that assume default
floating-point rounding behavior. This is round-to-zero for all
floating point to integer conversions, and round-to-nearest for all
other arithmetic truncations. This option should be specified for
programs that change the FP rounding mode dynamically, or that may
be executed with a non-default rounding mode. This option disables
constant folding of floating-point expressions at compile time
(which may be affected by rounding mode) and arithmetic
transformations that are unsafe in the presence of sign-dependent
rounding modes.
-ffast-math
在 gcc 中关闭宏。它不会在 clang 中这样做,这可能是一个错误。
因为他们好像有bug。
UPD.
- 将
__STDC_IEC_559__
定义为1
以防不符合附件F中的规范不是错误。 - 通常非严格的浮点模型意味着不符合附件 F 中的规范。如果是这样,则不清楚
__STDC_IEC_559__
定义为1
的目的。