Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: xref INT19-C

...

Code Block
bgColor#ccccff
langc
#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^si_b) &
       (((si_a ^ ((si_a^si_b) & INT_MIN)) -
         si_b)^si_b)) < 0) {
     /* Handle error condition */
  } else {
    result = si_a - si_b;
  }

  /* ... */
}

...

Code Block
bgColor#ccccff
langc
#include <assert.h>
 
signed int si_a;
signed int si_b;
signed int result;

void func(void) {
  /* Initialize si_a, si_b and result */
  assert( UWIDTH( signed long long, ULLONG_MAX) >=
          2 * UWIDTH( int, UINT_MAX));
  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;
  }
  /* ... */
}

The assertion fails if long long has less than twice the width of int. It relies on the UWIDTH() macro, which is defined in INT19-C.

...

Correctly compute integer widths.

On systems where this relationship does not existassertion would fail, the following compliant solution may be used to ensure signed overflow does not occur:

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
 
signed long s_a;
signed long s_b;
signed long result;

void func(void) {
  /* Initialize s_a, s_b and result */
  if ((s_b == 0 ) || ((s_a == LONG_MIN) && (s_b == -1))) {
    /* Handle error condition */
  } else {
    result = s_a % s_b;
  }

  /* ... */
}

...

Code Block
bgColor#ccccff
langc
#include <limits.h>

 
signed long s_a;
signed long result;

void func(void) {
  if ((si1 < 0) || (si2 < 0) ||
      (si2 >= UWIDTH(signed_int_width long, ULONG_MAX)) ||
      (si1 > (INT_MAX >> si2))) {
    /* handle error condition */
  } else {
    sresult = si1 << si2;
  }


  /* ... */
}

Anchor
Left Shift Operator
Left Shift Operator

This The UWIDTH() macro provides the correct width for an unsigned integer type, and is defined in INT19-C. Correctly compute integer widths...see that rule for more information. This solution also complies with INT34-C. Do not shift a negative number of bits or more bits than exist in the operand. See 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. 

...