...
This compliant solution guarantees there is no possibility of signed overflow on systems where long long
is at least twice the size width of int
:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <assert.h> signed int si_a; signed int si_b; signed int result; void func(void) { /* Initialize si_a, si_b and result */ static_assert( sizeof(long long) >= 2 * sizeof(int), "Unable to detect overflow after multiplication" ); signed long long tmp = (signed long long)si_a * (signed long long)si_b; /* * If the product cannot be represented as a 32-bit integer, * handle as an error condition. */ if ( (tmp > INT_MAX) || (tmp < INT_MIN) ) { /* Handle error condition */ } else { result = (int)tmp; } /* ... */ } |
...
On systems where this relationship does not exist, the following compliant solution may be used to ensure signed overflow does not occur:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> signed int si_a; signed int si_b; signed int result; void func(void) { /* Initialize si_a, si_b and result */ if (si_a > 0) { /* si_a is positive */ if (si_b > 0) { /* si_a and si_b are positive */ if (si_a > (INT_MAX / si_b)) { /* Handle error condition */ } } else { /* si_a positive, si_b nonpositive */ if (si_b < (INT_MIN / si_a)) { /* Handle error condition */ } } /* si_a positive, si_b nonpositive */ } else { /* si_a is nonpositive */ if (si_b > 0) { /* si_a is nonpositive, si_b is positive */ if (si_a < (INT_MIN / si_b)) { /* Handle error condition */ } } else { /* si_a and si_b are nonpositive */ if ( (si_a != 0) && (si_b < (INT_MAX / si_a))) { /* Handle error condition */ } } /* End if si_a and si_b are nonpositive */ } /* End if si_a is nonpositive */ result = si_a * si_b; } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> signed long s_a; signed long result; void func(void) { if ((si1 < 0) || (si2 < 0) || (si2 >= sizeof(int)*CHAR_BITsigned_int_width) || (si1 > (INT_MAX >> si2))) { /* handle error condition */ } else { sresult = si1 << si2; } /* ... */ } |
Anchor | ||||
---|---|---|---|---|
|
This solution is also compliant complies with INT34-C. Do not shift a negative number of bits or more bits than exist in the operand. However, a platform in which integers have some padding bits (that are not used to represent the integer's value) can have some some bits in si1
shifted in to the padding bitsSee that rule for how to compute the width of a signed int
.
Atomic Integers
The C Standard defines the behavior of arithmetic on atomic signed integer types to use two's complement representation with silent wraparound on overflow; there are no undefined results. However, although defined, these results may be unexpected and therefore carry similar risks to unsigned integer wrapping (see INT30-C. Ensure that unsigned integer operations do not wrap). Consequently, signed integer overflow of atomic integer types should also be prevented or detected.
...