gpt4 book ai didi

c++ - 为什么代码段会引发浮点异常?

转载 作者:行者123 更新时间:2023-12-01 14:39:16 25 4
gpt4 key购买 nike

这个

double what;
for (int i = 1; i < (long)pow(10, 7); i++)
what = (i + i) / (i * i) - i;

引发浮点异常(核心已转储)。为什么?
我正在使用clang++。

最佳答案

取决于您的平台,int可能为32或64位宽。

[basic.fundamental]/2[basic.fundamental]/3 [摘录,强调矿]:

[basic.fundamental]/2

There are five standard signed integer types : “signed char”, “short int”, “int”, “long int”, and “long long int”. In this list, each type provides at least as much storage as those preceding it in the list. [...] Plain ints have the natural size suggested by the architecture of the execution environment; the other signed integer types are provided to meet special needs.

[basic.fundamental]/3

For each of the standard signed integer types, there exists a corresponding (but different) standard unsigned integer type: “unsigned char”, “unsigned short int”, “unsigned int”, “unsigned long int”, and “unsigned long long int”, each of which occupies the same amount of storage and has the same alignment requirements as the corresponding signed integer type; [...]

The signed and unsigned integer types shall satisfy the constraints given in the C standard, section 5.2.4.2.1.



我们可以去 C11 Standard draft [摘录, 重点矿]:

5.2.4.2.1 Sizes of integer types <limits.h>

[...] Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign.

[...]

  • maximum value for an object of type int: INT_MAX +32767

[...]



但是,这在不了解目标/体系结构细节的情况下对我们没有帮助,因此,为了简化您的问题,让我们考虑使用固定宽度带符号整数的示例,并注意以下示例是“fine”(在这种情况下):
#include <cstddef>
#include <math.h>

int main() {
double what;
for (int32_t i = 1; i < (int32_t)pow(10, 4); i++)
{
what = (i + i) / (i * i) - i;
}
(void)what;
return 0;
}

而以下结果会导致我尝试执行的特定处决情况出现“浮点异常”(UB;龙可能会从我们的 Nose 中飞出,请参见下文):
#include <cstddef>
#include <math.h>

int main() {
double what;
for (int32_t i = 1; i < (int32_t)pow(10, 5); i++)
{
what = (i + i) / (i * i) - i;
}
(void)what;
return 0;
}

此处的关键是 int32_t的最大值是 2,147,483,647,这意味着 i * i将针对 pow(10, 5)大小的值溢出。有符号整数溢出是未定义的行为(UB),从那里开始,一切都会发生。在这种情况下,可能是UB, 与巧合,从表达式 0的溢出产生了一个值 i * i,这又导致表达式 (i + i) / (i * i)除以零(再次是UB),通过进一步的巧合又将 除以零,很可能是浮点异常的根本原因。

在这里,我要强调的是巧合,因为UB之外的任何观点都构成了无用的逻辑分析目标。编译器供应商可能会认为我们永远不会拥有UB,并且一旦进入UB域,一切都会做。除非您在特定的目标体系结构和硬件上使用C++的一些非标准方言进行工作,否则我们看到的任何结果都应视为偶然的,例如诸如带符号整数溢出之类的特定情况可以定义为非标准实现定义的(并因此由特定实现指定),而不是UB。

关于c++ - 为什么代码段会引发浮点异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62326261/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com