这个
double what;
for (int i = 1; i < (long)pow(10, 7); i++)
what = (i + i) / (i * i) - i;
引发浮点异常(核心转储)。为什么?我正在使用clang++。
这个
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
有五种标准有符号整数类型:“<code>signed char”、“<code>short int”、“<code>int”、“<code>long int”和“<code>long long int”。在此列表中,每种类型提供的存储空间至少与列表中它前面的类型一样多。[...] Plain
int具有执行环境架构所建议的自然大小;提供其他有符号整数类型以满足特殊需要。[basic.fundamental]/3
对于每个标准有符号整数类型,都存在相应的(但不同的)标准无符号整数类型:“<code>unsigned char”、“<code>unsigned short int”、“<code>unsigned int”、“<code >unsigned long int”和“<code>unsigned long long int”,每个占用的存储量和对应的有符号整数类型的对齐要求相同;[...]
有符号和无符号整数类型应满足 C 标准第 5.2.4.2.1 节中给出的约束。
我们可以查看C11 标准草案[摘录,强调我的]:
5.2.4.2.1 整数类型的大小
<limits.h>[...] 它们的实现定义值的大小(绝对值)应等于或大于所示值,且符号相同。
[...]
- 类型对象的最大值
int:INT_MAX +32767[...]
在不了解目标/架构细节的情况下,这对我们没有帮助,但是,为了简化您的问题,让我们考虑使用固定宽度有符号整数的示例,并注意以下示例“很好”(在这种情况下):
#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;龙可能会从我们的鼻子飞出,见下文):
#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;
}
这里的关键是 an 的最大值int32_t是2,147,483,647,这意味着i * i对于 的大小的值会溢出pow(10, 5)。有符号整数溢出是未定义的行为(UB),从那里开始任何事情都会发生。在这种情况下,可能巧合0的是,UB从表达式 的溢出中产生一个值i * i,这反过来又导致在表达式中除以零(再次 UB) (i + i) / (i * i),更巧合的是,它很可能是根浮点异常的情况。
我在这里强调的是巧合,因为超出 UB 的任何点都会成为逻辑分析的无用目标;编译器供应商可能会假设我们从来没有 UB 并且一旦我们进入 UB 域就会做任何事情。我们看到的任何结果都应视为巧合,除非您在特定目标体系结构和硬件上使用 C++ 的某些非标准方言工作,例如有符号整数溢出等特定情况可能被定义为非标准实现定义(并且因此由特定的实现指定)而不是UB。
您的int溢出是因为 10^14 不适合int我所见过的(请注意,这int取决于平台)。在某些平台上,10^7 已经溢出。有符号溢出总是导致未定义的行为,有时会导致0.
std::uint64_t或double直接存储循环变量。pow每个循环迭代。在循环外计算一次。循环中的i < (long)pow(10, 7)条件导致整数表达式变得大于其最大值,从而导致整数溢出和未定义的行为。在某些实现中,可能变为or ,导致以下表达式:
变为。例如,这反过来可能(在 Visual Studio 中)在调试期间导致整数除零异常。for(i * i)i01(i / i)0