将 double 转换为 int 时抛出浮点异常
floating point exception is thrown when casting double to int
考虑这段代码:
#include <iostream>
#include <climits>
#include <fenv.h>
int main()
{
feenableexcept(FE_INVALID);
double d = INT_MAX * 2.0f;
int i = (int)d; // it throws here fp exception and terminates. Why ?
std::cout << i << std::endl;
return 0;
}
这里首先要注意的是,将 double 转换为 int 会导致临时值溢出(超过 INT_MAX
),这当然是一般的未定义行为。
但我更关心的是,这里的 FP 异常可以通过将 FE_INVALID
常量标志传递给 feenableexcept
函数来捕获。
从 cpp_reference 可以看出 FE_INVALID
与溢出完全无关。
为什么这里整数溢出导致fp异常?
这是因为 UB 的性质吗?
因为这是C++标准的UB,当然不是语言本身指定的。
但是,您的实现遵循 IEEE-754——标准的大多数实现都基于它们的浮点行为——在这方面,它指出:
When a NaN or infinite operand cannot be represented in the destination format and this cannot otherwise
be indicated, the invalid operation exception shall be signaled. When a numeric operand would convert to
an integer outside the range of the destination format, the invalid operation exception shall be signaled if
this situation cannot otherwise be indicated.
(5.8 "Details of conversions from floating-point to integer formats",强调我的)
发出信号时如何处理这些异常留给实现;为他们设置陷阱是一种可能性。
考虑这段代码:
#include <iostream>
#include <climits>
#include <fenv.h>
int main()
{
feenableexcept(FE_INVALID);
double d = INT_MAX * 2.0f;
int i = (int)d; // it throws here fp exception and terminates. Why ?
std::cout << i << std::endl;
return 0;
}
这里首先要注意的是,将 double 转换为 int 会导致临时值溢出(超过 INT_MAX
),这当然是一般的未定义行为。
但我更关心的是,这里的 FP 异常可以通过将 FE_INVALID
常量标志传递给 feenableexcept
函数来捕获。
从 cpp_reference 可以看出 FE_INVALID
与溢出完全无关。
为什么这里整数溢出导致fp异常?
这是因为 UB 的性质吗?
因为这是C++标准的UB,当然不是语言本身指定的。
但是,您的实现遵循 IEEE-754——标准的大多数实现都基于它们的浮点行为——在这方面,它指出:
When a NaN or infinite operand cannot be represented in the destination format and this cannot otherwise be indicated, the invalid operation exception shall be signaled. When a numeric operand would convert to an integer outside the range of the destination format, the invalid operation exception shall be signaled if this situation cannot otherwise be indicated.
(5.8 "Details of conversions from floating-point to integer formats",强调我的)
发出信号时如何处理这些异常留给实现;为他们设置陷阱是一种可能性。