C++ 如何检测无符号整数乘法溢出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/199333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I detect unsigned integer multiply overflow?
提问by Chris Johnson
I was writing a program in C++ to find all solutions of ab= c, where a, band ctogether use all the digits 0-9 exactly once. The program looped over values of aand b, and it ran a digit-counting routine each time on a, band abto check if the digits condition was satisfied.
我正在用 C++ 编写一个程序来找到a b= c 的所有解决方案,其中a、b和c一起使用所有数字 0-9 一次。程序循环遍历a和b 的值,并且每次在a、b和a b上运行一个数字计数例程,以检查是否满足数字条件。
However, spurious solutions can be generated when aboverflows the integer limit. I ended up checking for this using code like:
但是,当a b溢出整数限制时,可能会生成伪解。我最终使用以下代码检查了这一点:
unsigned long b, c, c_test;
...
c_test=c*b; // Possible overflow
if (c_test/b != c) {/* There has been an overflow*/}
else c=c_test; // No overflow
Is there a better way of testing for overflow? I know that some chips have an internal flag that is set when overflow occurs, but I've never seen it accessed through C or C++.
有没有更好的方法来测试溢出?我知道有些芯片有一个在发生溢出时设置的内部标志,但我从未见过它通过 C 或 C++ 访问。
Beware that signedint
overflow is undefined behaviour in C and C++, and thus you have to detect it without actually causing it. For signed int overflow before addition, see Detecting signed overflow in C/C++.
请注意,有符号int
溢出是 C 和 C++ 中未定义的行为,因此您必须检测它而不实际引起它。对于加法之前的有符号整数溢出,请参阅检测 C/C++ 中的有符号溢出。
回答by pmg
I see you're using unsigned integers. By definition, in C(I don't know about C++), unsigned arithmetic does not overflow ... so, at least for C, your point is moot :)
我看到你在使用无符号整数。根据定义,在 C(我不知道 C++)中,无符号算术不会溢出......所以,至少对于 C,你的观点是没有实际意义的 :)
With signed integers, once there has been overflow, undefined behaviour(UB) has occurred and your program can do anything (for example: render tests inconclusive).
对于有符号整数,一旦发生溢出,就会发生未定义行为(UB),并且您的程序可以执行任何操作(例如:渲染测试不确定)。
#include <limits.h>
int a = <something>;
int x = <something>;
a += x; /* UB */
if (a < 0) { /* Unreliable test */
/* ... */
}
To create a conforming program, you need to test for overflow beforegenerating said overflow. The method can be used with unsigned integers too:
要创建符合要求的程序,您需要在生成所述溢出之前测试溢出。该方法也可以用于无符号整数:
// For addition
#include <limits.h>
int a = <something>;
int x = <something>;
if ((x > 0) && (a > INT_MAX - x)) /* `a + x` would overflow */;
if ((x < 0) && (a < INT_MIN - x)) /* `a + x` would underflow */;
// For subtraction
#include <limits.h>
int a = <something>;
int x = <something>;
if ((x < 0) && (a > INT_MAX + x)) /* `a - x` would overflow */;
if ((x > 0) && (a < INT_MIN + x)) /* `a - x` would underflow */;
// For multiplication
#include <limits.h>
int a = <something>;
int x = <something>;
// There may be a need to check for -1 for two's complement machines.
// If one number is -1 and another is INT_MIN, multiplying them we get abs(INT_MIN) which is 1 higher than INT_MAX
if ((a == -1) && (x == INT_MIN)) /* `a * x` can overflow */
if ((x == -1) && (a == INT_MIN)) /* `a * x` (or `a / x`) can overflow */
// general case
if (a > INT_MAX / x) /* `a * x` would overflow */;
if ((a < INT_MIN / x)) /* `a * x` would underflow */;
For division (except for the INT_MIN
and -1
special case), there isn't any possibility of going over INT_MIN
or INT_MAX
.
对于除法(除了INT_MIN
和-1
特殊情况),没有任何可能超过INT_MIN
或INT_MAX
。
回答by Head Geek
There isa way to determine whether an operation is likely to overflow, using the positions of the most-significant one-bits in the operands and a little basic binary-math knowledge.
有是一种方法来确定操作是否可能溢出,使用最显著一个位的操作对象的位置和一点点基本的二进制数学知识。
For addition, any two operands will result in (at most) one bit more than the largest operand's highest one-bit. For example:
此外,任何两个操作数将导致(至多)比最大操作数的最高一位多一位。例如:
bool addition_is_safe(uint32_t a, uint32_t b) {
size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
return (a_bits<32 && b_bits<32);
}
For multiplication, any two operands will result in (at most) the sum of the bits of the operands. For example:
对于乘法,任何两个操作数将导致(至多)操作数位之和。例如:
bool multiplication_is_safe(uint32_t a, uint32_t b) {
size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
return (a_bits+b_bits<=32);
}
Similarly, you can estimate the maximum size of the result of a
to the power of b
like this:
同样,你可以估算的结果的最大尺寸a
给力b
是这样的:
bool exponentiation_is_safe(uint32_t a, uint32_t b) {
size_t a_bits=highestOneBitPosition(a);
return (a_bits*b<=32);
}
(Substitute the number of bits for your target integer, of course.)
(当然,用目标整数替换位数。)
I'm not sure of the fastest way to determine the position of the highest one-bit in a number, here's a brute-force method:
我不确定确定数字中最高一位位置的最快方法,这是一种蛮力方法:
size_t highestOneBitPosition(uint32_t a) {
size_t bits=0;
while (a!=0) {
++bits;
a>>=1;
};
return bits;
}
It's not perfect, but that'll give you a good idea whether any two numbers could overflow before you do the operation. I don't know whether it would be faster than simply checking the result the way you suggested, because of the loop in the highestOneBitPosition
function, but it might (especially if you knew how many bits were in the operands beforehand).
它并不完美,但是在您执行操作之前,这会让您很好地了解是否有任何两个数字可能溢出。由于highestOneBitPosition
函数中的循环,我不知道它是否比简单地按照您建议的方式检查结果更快,但它可能(特别是如果您事先知道操作数中有多少位)。
回答by zneak
Clang 3.4+and GCC 5+offer checked arithmetic builtins. They offer a very fast solution to this problem, especially when compared to bit-testing safety checks.
Clang 3.4+和GCC 5+提供经过检查的算术内置函数。它们为这个问题提供了非常快速的解决方案,尤其是与位测试安全检查相比时。
For the example in OP's question, it would work like this:
对于 OP 问题中的示例,它的工作方式如下:
unsigned long b, c, c_test;
if (__builtin_umull_overflow(b, c, &c_test))
{
// Returned non-zero: there has been an overflow
}
else
{
// Return zero: there hasn't been an overflow
}
The Clang documentation doesn't specify whether c_test
contains the overflowed result if an overflow occurred, but the GCC documentation says that it does. Given that these two like to be __builtin
-compatible, it's probably safe to assume that this is how Clang works too.
c_test
如果发生溢出,Clang 文档没有指定是否包含溢出的结果,但 GCC 文档说它确实包含。鉴于这两个喜欢__builtin
兼容,可以安全地假设这也是 Clang 的工作方式。
There is a __builtin
for each arithmetic operation that can overflow (addition, subtraction, multiplication), with signed and unsigned variants, for int sizes, long sizes, and long long sizes. The syntax for the name is __builtin_[us](operation)(l?l?)_overflow
:
__builtin
对于 int 大小、long 大小和 long long 大小,每个算术运算都有一个可以溢出(加法、减法、乘法)的有符号和无符号变体。名称的语法是__builtin_[us](operation)(l?l?)_overflow
:
u
for unsignedors
for signed;- operation is one of
add
,sub
ormul
; - no
l
suffix means that the operands areint
s; onel
meanslong
; twol
s meanlong long
.
u
对于未签名或s
已签名;- 操作是
add
,sub
或 之一mul
; - 无
l
后缀表示操作数为int
s;一种l
手段long
;两个l
意思long long
。
So for a checked signed long integer addition, it would be __builtin_saddl_overflow
. The full list can be found on the Clang documentation page.
因此,对于检查的有符号长整数加法,它将是__builtin_saddl_overflow
. 完整列表可以在Clang 文档页面上找到。
GCC 5+ and Clang 3.8+ additionally offer generic builtins that work without specifying the type of the values: __builtin_add_overflow
, __builtin_sub_overflow
and __builtin_mul_overflow
. These also work on types smaller than int
.
GCC 5+ 和 Clang 3.8+ 还提供了通用内置函数,无需指定值的类型即可工作:__builtin_add_overflow
,__builtin_sub_overflow
和__builtin_mul_overflow
。这些也适用于小于int
.
The builtins lower to what's best for the platform. On x86, they check the carry, overflow and sign flags.
内置函数降低到最适合平台的程度。在 x86 上,他们检查进位、溢出和符号标志。
Visual Studio's cl.exe doesn't have direct equivalents. For unsigned additions and subtractions, including <intrin.h>
will allow you to use addcarry_uNN
and subborrow_uNN
(where NN is the number of bits, like addcarry_u8
or subborrow_u64
). Their signature is a bit obtuse:
Visual Studio的 cl.exe 没有直接等效项。对于无符号加法和减法,包括<intrin.h>
将允许您使用addcarry_uNN
和subborrow_uNN
(其中 NN 是位数,例如addcarry_u8
或subborrow_u64
)。他们的签名有点迟钝:
unsigned char _addcarry_u32(unsigned char c_in, unsigned int src1, unsigned int src2, unsigned int *sum);
unsigned char _subborrow_u32(unsigned char b_in, unsigned int src1, unsigned int src2, unsigned int *diff);
c_in
/b_in
is the carry/borrow flag on input, and the return value is the carry/borrow on output. It does not appear to have equivalents for signed operations or multiplications.
c_in
/b_in
是输入的进位/借位标志,返回值是输出的进位/借位。它似乎没有符号运算或乘法的等价物。
Otherwise, Clang for Windows is now production-ready (good enough for Chrome), so that could be an option, too.
否则,适用于 Windows 的 Clang 现在已经可以投入生产(对于 Chrome 来说已经足够了),因此这也可以成为一种选择。
回答by Robert Gamble
Some compilers provide access to the integer overflow flag in the CPU which you could then test but this isn't standard.
一些编译器提供对 CPU 中整数溢出标志的访问,然后您可以对其进行测试,但这不是标准的。
You could also test for the possibility of overflow before you perform the multiplication:
您还可以在执行乘法之前测试溢出的可能性:
if ( b > ULONG_MAX / a ) // a * b would overflow
回答by A Fog
Warning: GCC can optimize away an overflow check when compiling with -O2
.
The option -Wall
will give you a warning in some cases like
警告:GCC 可以在使用-O2
. 该选项-Wall
会在某些情况下向您发出警告,例如
if (a + b < a) { /* Deal with overflow */ }
but not in this example:
但不是在这个例子中:
b = abs(a);
if (b < 0) { /* Deal with overflow */ }
The only safe way is to check for overflow before it occurs, as described in the CERT paper, and this would be incredibly tedious to use systematically.
唯一安全的方法是在溢出发生之前检查溢出,如CERT 论文中所述,系统地使用这将非常乏味。
Compiling with -fwrapv
solves the problem, but disables some optimizations.
编译-fwrapv
解决了问题,但禁用了一些优化。
We desperately need a better solution. I think the compiler should issue a warning by default when making an optimization that relies on overflow not occurring. The present situation allows the compiler to optimize away an overflow check, which is unacceptable in my opinion.
我们迫切需要一个更好的解决方案。我认为编译器在进行依赖于不发生溢出的优化时默认情况下应该发出警告。目前的情况允许编译器优化掉溢出检查,这在我看来是不可接受的。
回答by ZAB
Clang now supports dynamic overflow checks for both signed and unsigned integers. See the -fsanitize=integerswitch. For now, it is the only C++ compiler with fully supported dynamic overflow checking for debug purposes.
Clang 现在支持对有符号和无符号整数进行动态溢出检查。请参阅-fsanitize=integer开关。目前,它是唯一一个完全支持动态溢出检查以用于调试目的的 C++ 编译器。
回答by hdante
I see that a lot of people answered the question about overflow, but I wanted to address his original problem. He said the problem was to find ab=c such that all digits are used without repeating. Ok, that's not what he asked in this post, but I'm still think that it was necessary to study the upper bound of the problem and conclude that he would never need to calculate or detect an overflow (note: I'm not proficient in math so I did this step by step, but the end result was so simple that this might have a simple formula).
我看到很多人回答了关于溢出的问题,但我想解决他原来的问题。他说问题是找到一个b= c 使得所有数字都被使用而不重复。好吧,这不是他在这篇文章中问的问题,但我仍然认为有必要研究问题的上限并得出结论,他永远不需要计算或检测溢出(注意:我不精通在数学中,所以我一步一步地做了这个,但最终结果非常简单,这可能有一个简单的公式)。
The main point is that the upper bound that the problem requires for either a, b or c is 98.765.432. Anyway, starting by splitting the problem in the trivial and non trivial parts:
要点是问题对 a、b 或 c 要求的上限是 98.765.432。无论如何,首先将问题分为琐碎和非琐碎的部分:
- x0== 1 (all permutations of 9, 8, 7, 6, 5, 4, 3, 2 are solutions)
- x1== x (no solution possible)
- 0b== 0 (no solution possible)
- 1b== 1 (no solution possible)
- ab, a > 1, b > 1 (non trivial)
- x 0== 1(9、8、7、6、5、4、3、2的所有排列都是解)
- x 1== x(无解)
- 0 b== 0(无解)
- 1 b== 1(无解)
- a b, a > 1, b > 1 (非平凡)
Now we just need to show that no other solution is possible and only the permutations are valid (and then the code to print them is trivial). We go back to the upper bound. Actually the upper bound is c ≤ 98.765.432. It's the upper bound because it's the largest number with 8 digits (10 digits total minus 1 for each a and b). This upper bound is only for c because the bounds for a and b must be much lower because of the exponential growth, as we can calculate, varying b from 2 to the upper bound:
现在我们只需要证明没有其他解决方案是可能的,只有排列是有效的(然后打印它们的代码是微不足道的)。我们回到上限。实际上上限是 c ≤ 98.765.432。它是上限,因为它是最大的 8 位数字(a 和 b 的 10 位总和减 1)。这个上限仅适用于 c,因为由于指数增长,a 和 b 的界限必须低得多,正如我们可以计算的那样,将 b 从 2 变化到上限:
9938.08^2 == 98765432
462.241^3 == 98765432
99.6899^4 == 98765432
39.7119^5 == 98765432
21.4998^6 == 98765432
13.8703^7 == 98765432
9.98448^8 == 98765432
7.73196^9 == 98765432
6.30174^10 == 98765432
5.33068^11 == 98765432
4.63679^12 == 98765432
4.12069^13 == 98765432
3.72429^14 == 98765432
3.41172^15 == 98765432
3.15982^16 == 98765432
2.95305^17 == 98765432
2.78064^18 == 98765432
2.63493^19 == 98765432
2.51033^20 == 98765432
2.40268^21 == 98765432
2.30883^22 == 98765432
2.22634^23 == 98765432
2.15332^24 == 98765432
2.08826^25 == 98765432
2.02995^26 == 98765432
1.97741^27 == 98765432
Notice, for example the last line: it says that 1.97^27 ~98M. So, for example, 1^27 == 1 and 2^27 == 134.217.728 and that's not a solution because it has 9 digits (2 > 1.97 so it's actually bigger than what should be tested). As it can be seen, the combinations available for testing a and b are really small. For b == 14, we need to try 2 and 3. For b == 3, we start at 2 and stop at 462. All the results are granted to be less than ~98M.
注意,例如最后一行:它表示 1.97^27 ~98M。因此,例如, 1^27 == 1 和 2^27 == 134.217.728 这不是解决方案,因为它有 9 位数字(2 > 1.97 所以它实际上比应该测试的要大)。可以看出,可用于测试 a 和 b 的组合非常小。对于 b == 14,我们需要尝试 2 和 3。对于 b == 3,我们从 2 开始,到 462 停止。所有结果都被授予小于 ~98M。
Now just test all the combinations above and look for the ones that do not repeat any digits:
现在只需测试上面的所有组合并查找不重复任何数字的组合:
['0', '2', '4', '5', '6', '7', '8'] 84^2 = 7056
['1', '2', '3', '4', '5', '8', '9'] 59^2 = 3481
['0', '1', '2', '3', '4', '5', '8', '9'] 59^2 = 3481 (+leading zero)
['1', '2', '3', '5', '8'] 8^3 = 512
['0', '1', '2', '3', '5', '8'] 8^3 = 512 (+leading zero)
['1', '2', '4', '6'] 4^2 = 16
['0', '1', '2', '4', '6'] 4^2 = 16 (+leading zero)
['1', '2', '4', '6'] 2^4 = 16
['0', '1', '2', '4', '6'] 2^4 = 16 (+leading zero)
['1', '2', '8', '9'] 9^2 = 81
['0', '1', '2', '8', '9'] 9^2 = 81 (+leading zero)
['1', '3', '4', '8'] 3^4 = 81
['0', '1', '3', '4', '8'] 3^4 = 81 (+leading zero)
['2', '3', '6', '7', '9'] 3^6 = 729
['0', '2', '3', '6', '7', '9'] 3^6 = 729 (+leading zero)
['2', '3', '8'] 2^3 = 8
['0', '2', '3', '8'] 2^3 = 8 (+leading zero)
['2', '3', '9'] 3^2 = 9
['0', '2', '3', '9'] 3^2 = 9 (+leading zero)
['2', '4', '6', '8'] 8^2 = 64
['0', '2', '4', '6', '8'] 8^2 = 64 (+leading zero)
['2', '4', '7', '9'] 7^2 = 49
['0', '2', '4', '7', '9'] 7^2 = 49 (+leading zero)
None of them matches the problem (which can also be seen by the absence of '0', '1', ..., '9').
它们都与问题不匹配(也可以通过缺少“0”、“1”、...、“9”来看出)。
The example code that solves it follows. Also note that's written in Python, not because it needs arbitrary precision integers (the code doesn't calculate anything bigger than 98 million), but because we found out that the amount of tests is so small that we should use a high level language to make use of its built-in containers and libraries (also note: the code has 28 lines).
解决它的示例代码如下。还要注意,它是用 Python 编写的,不是因为它需要任意精度的整数(代码不会计算任何大于 9800 万的东西),而是因为我们发现测试量太小了,我们应该使用高级语言来利用其内置的容器和库(另请注意:代码有 28 行)。
import math
m = 98765432
l = []
for i in xrange(2, 98765432):
inv = 1.0/i
r = m**inv
if (r < 2.0): break
top = int(math.floor(r))
assert(top <= m)
for j in xrange(2, top+1):
s = str(i) + str(j) + str(j**i)
l.append((sorted(s), i, j, j**i))
assert(j**i <= m)
l.sort()
for s, i, j, ji in l:
assert(ji <= m)
ss = sorted(set(s))
if s == ss:
print '%s %d^%d = %d' % (s, i, j, ji)
# Try with non significant zero somewhere
s = ['0'] + s
ss = sorted(set(s))
if s == ss:
print '%s %d^%d = %d (+leading zero)' % (s, i, j, ji)
回答by Angel Sinigersky
Here is a "non-portable" solution to the question. The Intel x86 and x64 CPUs have the so-called EFLAGS-register, which is filled in by the processor after each integer arithmetic operation. I will skip a detailed description here. The relevant flags are the "Overflow" Flag (mask 0x800) and the "Carry" Flag (mask 0x1). To interpret them correctly, one should consider if the operands are of signed or unsigned type.
这是该问题的“非便携式”解决方案。Intel x86 和 x64 CPU 具有所谓的EFLAGS 寄存器,它在每次整数算术运算后由处理器填充。我将在这里跳过详细说明。相关标志是“溢出”标志(掩码 0x800)和“进位”标志(掩码 0x1)。为了正确解释它们,应该考虑操作数是有符号还是无符号类型。
Here is a practical way to check the flags from C/C++. The following code will work on Visual Studio 2005or newer (both 32 and 64 bit), as well as on GNU C/C++ 64 bit.
这是从 C/C++ 检查标志的实用方法。以下代码适用于Visual Studio 2005或更新版本(32 位和 64 位)以及 GNU C/C++ 64 位。
#include <cstddef>
#if defined( _MSC_VER )
#include <intrin.h>
#endif
inline size_t query_intel_x86_eflags(const size_t query_bit_mask)
{
#if defined( _MSC_VER )
return __readeflags() & query_bit_mask;
#elif defined( __GNUC__ )
// This code will work only on 64-bit GNU-C machines.
// Tested and does NOT work with Intel C++ 10.1!
size_t eflags;
__asm__ __volatile__(
"pushfq \n\t"
"pop %%rax\n\t"
"movq %%rax, %0\n\t"
:"=r"(eflags)
:
:"%rax"
);
return eflags & query_bit_mask;
#else
#pragma message("No inline assembly will work with this compiler!")
return 0;
#endif
}
int main(int argc, char **argv)
{
int x = 1000000000;
int y = 20000;
int z = x * y;
int f = query_intel_x86_eflags(0x801);
printf("%X\n", f);
}
If the operands were multiplied without overflow, you would get a return value of 0 from query_intel_eflags(0x801)
, i.e. neither the carry nor the overflow flags are set. In the provided example code of main(), an overflow occurs and the both flags are set to 1. This check does not imply any further calculations, so it should be quite fast.
如果操作数相乘而没有溢出,您将得到 0 的返回值query_intel_eflags(0x801)
,即既不设置进位也不设置溢出标志。在提供的 main() 示例代码中,发生溢出并且两个标志都设置为 1。此检查不意味着任何进一步的计算,因此它应该非常快。
回答by Evan Teran
If you have a datatype which is bigger than the one you want to test (say you do a 32-bit add and you have a 64-bit type), then this will detect if an overflow occurred. My example is for an 8-bit add. But it can be scaled up.
如果您的数据类型大于您要测试的数据类型(假设您执行 32 位加法并且您有一个 64 位类型),那么这将检测是否发生溢出。我的例子是 8 位加法。但它可以放大。
uint8_t x, y; /* Give these values */
const uint16_t data16 = x + y;
const bool carry = (data16 > 0xFF);
const bool overflow = ((~(x ^ y)) & (x ^ data16) & 0x80);
It is based on the concepts explained on this page: http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/Comb/overflow.html
它基于此页面上解释的概念:http: //www.cs.umd.edu/class/spring2003/cmsc311/Notes/Comb/overflow.html
For a 32-bit example, 0xFF
becomes 0xFFFFFFFF
and 0x80
becomes 0x80000000
and finally uint16_t
becomes a uint64_t
.
对于 32 位示例,0xFF
变成0xFFFFFFFF
和0x80
变成0x80000000
,最后uint16_t
变成uint64_t
.
NOTE: this catches integer addition/subtraction overflows, and I realized that your question involves multiplication. In which case, division is likely the best approach. This is commonly a way that calloc
implementations make sure that the parameters don't overflow as they are multiplied to get the final size.
注意:这会捕获整数加法/减法溢出,我意识到您的问题涉及乘法。在这种情况下,划分可能是最好的方法。这通常是calloc
实现确保参数在相乘以获得最终大小时不会溢出的一种方式。
回答by Andrew Edgecombe
The simplest way is to convert your unsigned long
s into unsigned long long
s, do your multiplication, and compare the result to 0x100000000LL.
最简单的方法是将您的unsigned long
s 转换为unsigned long long
s,进行乘法,然后将结果与 0x100000000LL 进行比较。
You'll probably find that this is more efficient than doing the division as you've done in your example.
您可能会发现这比在示例中进行除法更有效。
Oh, and it'll work in both C and C++ (as you've tagged the question with both).
哦,它可以在 C 和 C++ 中工作(因为你已经用两者标记了问题)。
Just been taking a look at the glibc manual. There's a mention of an integer overflow trap (FPE_INTOVF_TRAP
) as part of SIGFPE
. That would be ideal, apart from the nasty bits in the manual:
刚刚看了一下glibc 手册。提到了整数溢出陷阱 ( FPE_INTOVF_TRAP
) 作为SIGFPE
. 这将是理想的,除了手册中令人讨厌的部分:
FPE_INTOVF_TRAP
Integer overflow (impossible in a C program unless you enable overflow trapping in a hardware-specific fashion).
FPE_INTOVF_TRAP
整数溢出(在 C 程序中不可能,除非您以特定于硬件的方式启用溢出捕获)。
A bit of a shame really.
真的有点可惜。