GCC 的 __builtin_isnan 是否做了 isnan 之外的其他事情?

问题描述 投票:0回答:2

GCC内置描述中,它说:

GCC 提供内置版本的 ISO C99 浮点比较宏,以避免引发无序操作数的异常。它们与标准宏具有相同的名称(isgreater、isgreaterequal、isless、islessequal、islessgreater 和 isunordered),并带有 _builtin 前缀。我们希望库实现者能够简单地将每个标准宏#define 为其内置等效宏。以同样的方式,GCC 提供了 fpclassify、isfinite、isinf_sign、isnormal 和 signbit 内置函数,并以 _builtin 为前缀。 isinf 和 isnan 内置函数在带或不带 _builtin 前缀时都会出现。

所以,我不太能够解析这个。浮点比较什么时候应该引发异常? C 标准强制要求他们这样做吗?强制他们不这样做?没有强制要求什么吗?并且 -

__builtin_isnan()
的作用与
isnan()
不同吗?

gcc floating-point c99 built-in isnan
2个回答
2
投票

这里的例外情况是,GCC 文档指的是 IEEE 754 浮点例外。如果你做类似的事情

a < b

并且其中一个操作数是 NaN,将引发 FP 异常(无效)。这意味着 FPU 中的某个位将保持设置状态,直到被程序员明确清除为止。通过使用

isgreater
/
isless
/等。程序员可以避免触发 FP 异常。


0
投票

GCC 的标准库函数的内置函数主要用于优化,当某些参数或环境约束可以在编译时已知时。

__builtin_isnan()
以类似的方式工作。

__builtin_isnan()
的主要目的是在禁用信号NaN支持时允许将
isnan(x)
优化为
(x != x)
(即
-fno-signaling-nans
,这是默认值)。

isnan(x)
(x != x)
的行为并不相同。差异在于评估信号 NaN 时。

(以上是问题的主要回答,以下是更多技术细节。)


IEEE 754(标准)定义了“安静”NaN 和“信号”NaN,彻底了解它们可能会让您头疼。 (我是认真的。)

如果您不熟悉 IEEE 浮点及其比较操作,这里有一些基础知识:

  • 比较两个 IEEE 754 浮点有四种可能的结果(或关系):“小于”、“等于”、“大于”和“无序”。当一个或两个操作数都是 NaN 时,就会出现“无序”结果。这也意味着
    !(x > y)
    不等于浮点数中的
    (x <= y)
  • IEEE 754 定义了“安静”和“信号”比较操作,区别在于它们是否以及何时生成浮点异常。

“安静”和“信号”术语是相对的,我将它们添加到引号中,因为“安静”比较并不总是安静,而“信号”并不总是发出信号。

IEEE 754 中的“安静”比较映射到 C 中的这些:

(x==y)
isgreater
isgreaterequal
isless
islessequal
isunordered

IEEE 754 中的“信号”比较映射到 C 中的这些:

iseqsig
(x>y)
(x>=y)
(x<y)
(x<=y)
isunordered
没有“信号”变体,因为这没有意义。

对于“安静”比较,它们不会用安静的 NaN 操作数引发 FP 异常。 但是 当任何操作数是信号 NaN 时,它们确实会抛出“无效操作”(FE_INVALID) 异常。

对于“信号”比较,当任何操作数为 NaN 时,无论其信号位如何,它们都会引发异常。 (也就是说,它们也会对安静的 NaN 抛出异常。)

还有一些函数永远不会抛出异常,即使存在信号 NaN。

fpclassify
函数,包括
isnan
,都是这样的。 (这些也是 IEEE 754 中的标准操作,尽管不同的语言为这些操作提供了不同的 API。)

这个关于 isnan() 和 (x!=x) 的 Stack Overflow 答案中我做了一个快速比较表:

              | isnan(x) | (x != x)  | (x >= x)   | isgreaterequal(x,x)
--------------+----------+-----------+------------+--------------------
-Wfloat-equal | no warn  | warn      | no warn    | no warn
--------------+----------+-----------+------------+--------------------
Finite number | false    | false     | true       | true
Infinity      | false    | false     | true       | true
NaN (quiet)   | true     | true      | FPE; false | false
SNaN          | true     | FPE; true | FPE; false | FPE; false

因此您可以了解

isnan
!=
>=
isgreaterequal
在不同类型的浮点值上的表现。

© www.soinside.com 2019 - 2024. All rights reserved.