Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added back left shift example

...

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, and E1 × 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
bgColor#FFcccc
langc
#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
bgColor#ccccff
langc
#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
Unary Negation
Unary Negation

...

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
bgColor#FFcccc
langc
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
bgColor#FFcccc
langc
#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.

...