在 C89 中,不允许 FP 收缩。从 C99 开始,默认情况下实现可以对表达式进行 FP 收缩,但随后需要提供一个#pragma STDC FP_CONTRACT
( cppreference ) 可以切换以影响收缩行为。
所以GCC开关应该是:
-ffp-contract=off
: 不要收缩。忽略#pragma STDC FP_CONTRACT
。这是-std=c89
.
-ffp-contract=on
:默认启用收缩和荣誉#pragma STDC FP_CONTRACT
。这将是-std=c99
及以上的默认值。
-ffp-contract=fast
:这是 GCC 的默认设置,即使没有任何快速数学选项。 我们不要求在快速数学模式下符合 ISO 标准,因此可以始终收缩,甚至是单独的表达式(参见 Marc Glisse 的评论)。这是-std=gnu99
C 语言和其他 GNU 方言的默认设置。
不幸的是,#pragma STDC FP_CONTRACT
它还没有在 GCC 中实现,所以现在gcc -ffp-contract=on
要做的是保持 ISO 一致:什么都没有。即 on = off,因为 GCC 知道如何实现(快速)的唯一其他行为对于on
.
您必须深入研究来源(或邮件列表)以查看 GCC 能够执行哪些类型的收缩,但它不必仅限于 FMA。
有关一个表达式与 2 个语句的简单测试用例, 请参阅Godbolt 上的 GCC 和 Clang 。如您所见,Clang 默认为-ffp-contract=off
但支持on
and 。fast
GCC 仅支持off
and fast
,on
映射到off
.
C11 标准有什么要说的#pragma STDC FP_CONTRACT
:
§6.5¶8:浮动表达式可以收缩,也就是说,像单个操作一样进行评估,从而省略源代码和表达式评估方法隐含的舍入错误。89) <math.h> 中的 FP_CONTRACT 杂注提供了一种禁止收缩表达式的方法。否则,表达式是否以及如何收缩是实现定义的。90)
压缩表达式中的中间操作被评估为无限范围和精度,而最终操作被四舍五入为表达式评估方法确定的格式。收缩的表达式也可能会省略引发浮点异常。
该许可证专门用于允许实现利用结合多个 C 运算符的快速机器指令。由于收缩可能会破坏可预测性,甚至会降低包含表达式的准确性,因此它们的使用需要明确定义并清楚地记录在案。