在GCC built-ins description中,它说:
GCC提供了ISO C99浮点比较宏的内置版本,避免了对无序操作数引发异常。它们与标准宏具有相同的名称(isgreater,isgreaterequal,isless,islessequal,islessgreater,and isunordered),加上_builtin 前缀。我们希望库实现者能够简单地将每个标准宏定义为其内置等效宏。以同样的方式,GCC提供了fpclassify、isfinite、isinf_sign、isnormal和signbit内置函数,这些内置函数使用_builtin 前缀。isinf和isnan内置函数既可以使用_builtin 前缀,也可以不使用_builtin 前缀。
所以,我不太能解析这个。浮点数比较什么时候应该引发异常?C标准强制它们这样做吗?强制它们不这样做吗?没有强制任何东西吗?__builtin_isnan()
的行为与isnan()
不同吗?
2条答案
按热度按时间jfgube3f1#
这里的异常,GCC文档指的是IEEE 754浮点异常。
字符串
并且其中一个操作数是NaN,将引发FP异常(无效)。这意味着FPU中的一个位将保持设置状态,直到程序员显式清除它。通过使用
isgreater
/isless
/etc。程序员可以避免触发FP异常。nxowjjhe2#
GCC内置的标准库函数主要用于优化,当某些参数或环境约束可以在编译时知道时。
__builtin_isnan()
的主要目的是允许在禁用NaN支持时将isnan(x)
优化为(x != x)
(即-fno-signaling-nans
,默认值)。isnan(x)
和(x != x)
的行为并不相同。在评估信令NaN时存在差异。(以上是问题的主要答案。以下是更多的技术细节。)
IEEE754(标准)定义了“安静”的NaN和“信令”的NaN,这可能是一个令人头痛的问题,让你彻底了解它们。(我是认真的。)
如果你是IEEE浮点运算及其比较运算的新手,这里有一些基础知识:
!(x > y)
在浮点数中不等同于(x <= y)
。(但是,!(x == y)
和(x != y)
是等价的。)“安静”和“信号”术语是相对的,我把它们加在吓人的引号里,因为“安静”的比较并不总是安静的,而“信号”并不总是信号。
IEEE 754中的“安静”比较Map到C中的这些:
(x == y)
,isgreater
,isgreaterequal
,isless
,islessequal
,isunordered
。IEEE 754中的“信令”比较Map到C中的这些:
iseqsig
,(x > y)
,(x >= y)
,(x < y)
和(x <= y)
。没有isunordered
的“信令”变体,因为这没有意义。对于“安静”比较,它们不会抛出带有安静NaN操作数的FP异常。* 但是 * 当任何操作数是一个信号NaN时,它们会抛出“无效操作”(FE_INVALID)异常。
对于“信号”比较,当任何一个操作数是NaN时,不管它的信号位是多少,它们都会抛出异常(也就是说,它们也会在安静的NaN上抛出异常)。
还有一些函数,即使存在NaN信号,也不会抛出异常。
fpclassify
函数,包括isnan
,就是这种类型。(这些也是IEEE 754中的标准操作,尽管不同的语言为这些提供了不同的API。)在this Stack Overflow answer about isnan() and (x != x)中,我做了一个快速比较表:
字符串
true
和false
分别指宏的非零和0
返回值(它们的返回类型是int
,而不是bool
)。“FPE”表示宏或表达式产生“无效操作”异常。*因此,您可以了解
isnan
,!=
,>=
和isgreaterequal
在不同类型的浮点值上的行为。