...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef.h> #include <assert.h> #include <limits.h> #include <inttypes.h> extern size_t popcount(uintmax_t num) { size_t width = 0; while (num != 0) { if (num % 2 == 1) { width++; } num >>= 1; } return width; } #define UWIDTH(umax_value) popcount(umax_value) void func(signed int si_a, signed int si_b) { signed int result; signed long long tmp; assert(UWIDTH(ULLONG_MAX) >= 2 * UWIDTH(UINT_MAX)); 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 */ } else { result = (int)tmp; } /* ... */ } |
The assertion fails if long long
has less than twice the width of int
. The UWIDTH()
macro and popcount()
function are explained in INT35-C. Use correct integer widthsprecisions. The following portable compliant solution can be used for on any conforming implementation, including those where this assertion fails:
...
The C Standard, 6.5.7 paragraph 4 [ISO/IEC 9899:2011], states
...
In almost every case, an attempt to shift by a negative number of bits or by more bits than exist in the operand indicates a bug (logic error). These issues are covered by INT34-C. Do not shift a negative number of bits or more bits than exist in the operand.
Noncompliant Code Example
This noncompliant code example can result in an unrepresentable value.
...
Compliant Solution
This compliant solution eliminates the possibility of overflow resulting from a left-shift operation:
...
...