To detectint overflow/underflow in C, I use this code. What might be a simpler and more portable way of coding this (that is, fewer conditions)?
Assume 2's complement and don't use wider integers.
int a,b,sum;sum = a + b;// out-of-range only possible when the signs are the same.if ((a < 0) == (b < 0)) { if (a < 0) { // Underflow here means the result is excessively negative. if (sum > b) UnderflowDetected(); } else { if (sum < b) OverflowDetected(); }- 1\$\begingroup\$I think you're misunderstanding underflow ... or am I? Let's say, as an example, the smallest number a
floatcan represent is0.001.1.0 / 10000would result in a value of0.0because the actual value is too small.\$\endgroup\$Fiddling Bits– Fiddling Bits2013-12-12 00:44:09 +00:00CommentedDec 12, 2013 at 0:44 - 2\$\begingroup\$@BitFiddlingCodeMonkey this is on integers - there are various wrap-around cases where the result of an addition does not fit in the same size integer. Sometimes it's called underflow when it's the sum of two negative numbers that doesn't fit.\$\endgroup\$Michael Urman– Michael Urman2013-12-12 01:01:47 +00:00CommentedDec 12, 2013 at 1:01
- 3\$\begingroup\$If you just change from usingint to usingunsigned int, or better still,uint32_t andsize_t, you'll be able to do those checks after the operation. For signedints, overflow and underflow can't be detected after-the-fact because of undefined behaviour. And be warned: undefined behaviour can exhibit itself as anything from the program appearing to work properly right through to malware being installed on your machine and being used to steal your credit card information.\$\endgroup\$Matt– Matt2013-12-12 12:10:06 +00:00CommentedDec 12, 2013 at 12:10
- 2\$\begingroup\$@chux: No - I was merely pointing out that the method employed here (i.e. do an add and then see if an overflow occurred) is valid only on unsigned integers. For signed integers it is never valid because overflow of signed integers is inherently undefined in the language.\$\endgroup\$Matt– Matt2013-12-12 15:52:54 +00:00CommentedDec 12, 2013 at 15:52
- 2\$\begingroup\$From GCC 5, there arebuiltin functions to do this.\$\endgroup\$o11c– o11c2015-06-17 23:09:52 +00:00CommentedJun 17, 2015 at 23:09
4 Answers4
It's not possible to avoid undefined behaviour by testing for it after the fact! If the addition overflows then there is already undefined behaviour here:
sum = a + b;so attempting to test afterwards is too late. You have to test for possible overflowbefore you do a signed addition. (If you're puzzled by this, read Dietz et al. (2012), "Understanding Integer Overflow in C/C++". Or even you're not puzzled: it's an excellent paper!)
If it were me, I'd do something like this:
#include <limits.h>int safe_add(int a, int b) { if (a > 0 && b > INT_MAX - a) { /* handle overflow here */ } else if (a < 0 && b < INT_MIN - a) { /* handle underflow here */ } return a + b;}but I'm not entirely sure what the point of having separate cases for overflow and underflow is.
I also use Clang's-fsanitize=undefined when building for test.
Update (2023) Several modern compilers now have built-in functions for arithmetic with overflow checking. For example, using GCC's__builtin_add_overflow, we could implementsafe_add like this:
int safe_add(int a, int b) { int sum; if (__builtin_add_overflow(a, b, &sum)) { /* handle overflow or underflow here */ } else { return sum; }}- 1\$\begingroup\$§5.2.4.2.1 in theC99 standard defines
INT_MINto be the "minimum value for an object of typeint" andINT_MAXto be the "maximum value for an object of typeint".\$\endgroup\$Gareth Rees– Gareth Rees2013-12-11 23:20:18 +00:00CommentedDec 11, 2013 at 23:20 - 1\$\begingroup\$@Jamal Actually, with
<limits>.std::numeric_limits<int>::min()andstd::numeric_limits<int>::max()to be precise.\$\endgroup\$Yuushi– Yuushi2013-12-12 00:16:51 +00:00CommentedDec 12, 2013 at 0:16 - 3\$\begingroup\$It's worth pointing out that integer overflow and underflow are undefined only for SIGNED types. For unsigned integers, overflow safely occurs as modulo arithmetic.\$\endgroup\$Matt– Matt2013-12-12 12:02:50 +00:00CommentedDec 12, 2013 at 12:02
- 2\$\begingroup\$@Max: That would have undefined behaviour if
a + boverflowed, and undefined behaviour is what we are trying to avoid! (But also, even ifa + bwere defined, your expression could not work, becausea + bis anint, and all values ofintare less than or equal toINT_MAX.)\$\endgroup\$Gareth Rees– Gareth Rees2013-12-13 13:36:15 +00:00CommentedDec 13, 2013 at 13:36 - 1\$\begingroup\$There is a use for separate cases in doing saturating arithmetic.\$\endgroup\$Deduplicator– Deduplicator2017-07-15 15:59:25 +00:00CommentedJul 15, 2017 at 15:59
Simpler method to detect int overflow...
The two simplest methods I know are:
SafeInt was written by David LeBlanc, and Microsoft uses it.safe_iop was written by ???, and Android uses it.
The next simplest method is to use a compiler intrinsic. Unfortunately, I have not seen many of them. I believe I saw some for GCC recently.
The neat thing about intrinsics are (1) they provide a familiar C function call and (2) they are not bound by the Undefined Behavior you are trying to avoid. That means an instrinsiccan perform the addition and the program will still be well defined, even it it overflows.
(In C/C++, if you perform the addition and it overflows, then the program is illegal. You are not allowed to perform the operation and then check the result).
The next simplest method is assembly and inline assembly. Again, its not bound by the Undefined Behavior you are trying to avoid in C/C++.
Assembly and inline assembly routines are the method I use. I work on mobile platforms and I have a library for i686, x86_64, ARM and MIPS.
I learned a long time ago its a pain in the butt to try and do this cross-platform in a well defined, portable and efficient manner from C, especially for some operations.
I was constantly checking results of compilations and starring at disassembled code to make sure the code generation was good. So I abandoned portable in the name of simplicity and efficiency.
Also seeHow to detect integer overflow in C/C++? on Stack Overflow.
- \$\begingroup\$As of late 2018 there's a Boost library very similar to SafeInt:boost.org/doc/libs/1_74_0/libs/safe_numerics/doc/html/tutorial/…\$\endgroup\$Max Barraclough– Max Barraclough2020-09-24 10:17:21 +00:00CommentedSep 24, 2020 at 10:17
Why not use a long to hold the result of the calculation? Then the long can be checked against the (int) MAX and MIN values to see if overflow or underflow occurred? If no violations have occurred, then the result can safely be re-cast back to an (int).
Or, is this too simple and I'm missing something very fundamental? One thing that I HAVE omitted is the possibility that the long will also overflow.
- 4\$\begingroup\$As type
longis only guaranteed to beat least the range ofint, converting tolongmay not provide any additional range. Thus the problem is fundamentally the same forlongas forint. Same situation forlong long.\$\endgroup\$chux– chux2014-07-06 17:18:58 +00:00CommentedJul 6, 2014 at 17:18 - \$\begingroup\$While it's is technically true that
long longis only guaranteed to be at least as long asint, I'm not aware of any platform that actually implementslong longusing the same number of bytes asint. So in practice, this solution just works, plus it's much simpler.\$\endgroup\$Samuel Li– Samuel Li2019-03-25 05:29:44 +00:00CommentedMar 25, 2019 at 5:29 - \$\begingroup\$@SamuelLi Just because it works doesn't mean it's portable.\$\endgroup\$S.S. Anne– S.S. Anne2020-01-22 12:18:17 +00:00CommentedJan 22, 2020 at 12:18
- \$\begingroup\$@S.S.Anne While your statement is true, but since there are only a handful of platforms there and none is emerging in the near future, I'd say this is a portable solution for available platforms today and many years to come.\$\endgroup\$Samuel Li– Samuel Li2020-01-23 15:53:59 +00:00CommentedJan 23, 2020 at 15:53
- 2\$\begingroup\$@SamuelLi The ILP64 ABI of x86_64 has a 64-bit
int,long, andlong long.\$\endgroup\$S.S. Anne– S.S. Anne2020-01-23 16:14:15 +00:00CommentedJan 23, 2020 at 16:14
Overflow and underflow can happen in two cases : either
- Both negative numbers and sum becomes positive or
- Both positive numbers and sum becomes negative.
Then you can use this logical expression:
((a<0)&&(b<0)&&(a+b>0)) || ((a>0)&&(b>0)&&(a+b<0))or if you prefer integer arithmetics to logical expressions:
(a<0)*(b<0)*(a+b>0) + (a>0)*(b>0)*(a+b<0)In two complements one can be pedantic and just pick out the sign bit to do operations on, or even in hardware.
- 2\$\begingroup\$That's not exactlyportable, given that you're invoking Undefined Behaviour and then attempting a test for it afterwards. This solution fails in systems with saturating arithmetic, for example.\$\endgroup\$Toby Speight– Toby Speight2017-09-19 10:04:35 +00:00CommentedSep 19, 2017 at 10:04
- \$\begingroup\$@TobySpeight : Yes you are right. I guess I haven't worked enough with those saturating arithmetics to think about it automatically. We can do some constant compile time tests from the start to determine that and use macros to decide if to compile our code or the saturated code.\$\endgroup\$mathreadler– mathreadler2017-09-19 10:29:46 +00:00CommentedSep 19, 2017 at 10:29
- 1\$\begingroup\$If you add a
long longto achar, you could still overflow with all positive numbers. I didn't downvote, just wanted to point this out.\$\endgroup\$James M. Lay– James M. Lay2022-01-10 20:04:23 +00:00CommentedJan 10, 2022 at 20:04
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.



