Preventing C integer overflow

In C the header file you want is <stdint.h> and the constant is UINT32_MAX

static void update_value(char op)
{
    if (op == '+')
        if ( value < (UINT32_MAX - 1))
            value++;    // uint32_t global value
        else
            printf("too big!\n");
    else
       if (value > 0)
           value--;
       else
           printf("too small!\n");
}

For C++ you can use any number of solutions found here: What's the C++ equivalent of UINT32_MAX?


I've found that the most general solution is to check if the incremented value is in fact greater than the previous value, or if the decremented value is smaller than the previous value. This works only if the value is unsigned, independently of the size of the variable, and is pretty much as portable as C code ever gets.

static void update_value(char op)
{
  if (op == '+') {
    if (value + 1 > value) value ++;
  } else {
    if (value - 1 < value) value --;
  }
}

Note that the code may happen to work with signed values, but per the C standard this would be undefined behavior, and the compilers are free to replace if (value + 1 > value) ... with if (1) .... You should not use this code with signed values unless you have a process in place to audit the generated object code after it has been linked.

With gcc and clang, you'd need to add -fwrapv option to let this code work for signed values; with other compilers your mileage may vary.

A sane way of doing this is to be type-specific and use constants from limits.h. For example:

#include "limits.h"

static void update_int(char op, int *value)
{
  int val = *value; // ignoring NULL pointer dereference

  if (op == '+') {
    if (val != INT_MAX) *value = val + 1;
  } else {
    if (val != INT_MIN) *value = val - 1;
  }
}

static void update_int(char op, unsigned int *value)
{
  unsigned int val = *value; // ignoring NULL pointer dereference

  if (op == '+') {
    if (val != UINT_MAX) *value = val + 1;
  } else {
    if (val != UINT_MIN) *value = val - 1;
  }
}

Maybe you are looking for <limits>: http://www.cplusplus.com/reference/limits/numeric_limits/

You can do something like this to get what you want:

unsigned int n = numeric_limits<unsigned int>::max()

You also have this <cstdint>: http://www.cplusplus.com/reference/cstdint/

UINTN_MAX: Maximum value of exact-width unsigned type (Exactly 2^N-1)

Tags:

Linux

C++

C