...
The left-shift operator takes two operands of integer type. For examples of usage of the left-shift operator, see INT34-C. Do not shift a negative number of bits or more bits than exist in the operand.The result of E1 << E2
is E1
left-shifted E2
bit positions; vacated bits are filled with zeros.
The C Standard, 6.5.7 paragraph 4 [ISO/IEC 9899:2011], states
If
E1
has a signed type and nonnegative value, andE1 × 2E2
is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
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.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h>
#include <stddef.h>
#include <inttypes.h>
extern size_t popcount(uintmax_t);
#define UWIDTH(umax_value) popcount(umax_value)
void func(signed long si_a, signed long si_b) {
signed long result;
if ((si_a < 0) || (si_b < 0) ||
(si_b >= UWIDTH(ULONG_MAX)) {
/* Handle error */
} else {
result = si_a << si_b;
}
/* ... */
} |
Compliant Solution
This compliant solution eliminates the possibility of overflow resulting from a left-shift operation:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h>
#include <stddef.h>
#include <inttypes.h>
extern size_t popcount(uintmax_t);
#define UWIDTH(umax_value) popcount(umax_value)
void func(signed long si_a, signed long si_b) {
signed long result;
if ((si_a < 0) || (si_b < 0) ||
(si_b >= UWIDTH(ULONG_MAX)) ||
(si_a > (LONG_MAX >> si_b))) {
/* Handle error */
} else {
result = si_a << si_b;
}
/* ... */
} |
The UWIDTH()
macro provides the correct width for an unsigned integer type (see INT19-C. Correctly compute integer widths).
Anchor | ||||
---|---|---|---|---|
|
...
The unary negation operator takes an operand of arithmetic type. Overflow can occur during two's complement unary negation when the operand is equal to the minimum (negative) value for the signed integer type.
Noncompliant Code Example
This noncompliant code example can result in a signed integer overflow during the unary negation of the signed operand s_a
:
Code Block | ||||
---|---|---|---|---|
| ||||
void func(signed long s_a) { signed long result = -s_a; /* ... */ } |
Compliant Solution
This compliant solution tests the suspect negation operation to guarantee there is no possibility of signed overflow:
...
This section includes an example for the addition of atomic integer types only. For other operations, tests similar to the precondition tests for two’s complement integers used for nonatomic integer types can be used.
Noncompliant Code Example
This noncompliant code example using atomic integers can result in unexpected signed integer overflow:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdatomic.h> atomic_int i; void func(int si_a) { atomic_init(&i, 42); atomic_fetch_add(&i, si_a); /* ... */ } |
Compliant Solution
This compliant solution tests the operands to guarantee there is no possibility of signed overflow. It loads the value stored in the atomic integer and tests for possible overflow before performing the addition. However, this code contains a race condition where i
can be modified after the load, but prior to the atomic store. This solution is only compliant if i
is guaranteed to only be access by a single thread. See CON43-C. Do not assume that a group of calls to independently atomic methods is atomic for more information.
...