Search code examples
cfunctionintegerlong-integerinteger-overflow

best way to recognize and handle integer overflow in c?


I am so new in C and so far I didn't comprehend how to prevent from integer overflow, I read many articles but still I am not 100% sure! in this case

int ft_sqrt(int nb)
{
    long int    sqrt;
    
    if (nb <= 0)
        return (0);
    if (nb == 1)
        return (1); 
    sqrt = 1;
    while (sqrt * sqrt < nb)
    {
        sqrt++;
    }
    if (sqrt * sqrt == nb)
        return (sqrt);
    else
        return (0);
}

to prevent overflow should I use

long

? what is the best practice to do that?


Solution

  • long is not certainly wider than int and so its use may not widen the computation.


    To certainly avoid overflow, don't multiple, but divide.

    int ft_sqrt(int nb) {
        int    sqrt;
        if (nb <= 0)
            return (0);
        if (nb == 1)
            return (1); 
        sqrt = 1;
        // while (sqrt * sqrt < nb)
        while (sqrt < nb / sqrt) {
            sqrt++;
        }
        if (sqrt == nb / sqrt)
            return (sqrt);
        else
            return (0);
    }
    

    Yes code takes a performance hit - yet OP algorithm has many ways for improvement)


    Alternate code:

    unsigned bit_width(unsigned x) {
      unsigned width = 0;
      while (x) {
        x /= 2;
        width++;
      }
      return width;
    }
    
    unsigned usqrt(unsigned x) {
      if (x == 0) {
        return 0;
      }
      unsigned y = 1u << bit_width(x) / 2;
      unsigned y_previous;
      unsigned diff;
      unsigned diff1count = 0;
    
      do {
        y_previous = y;
        y = (y + x / y) / 2;
        diff = y_previous < y ? y - y_previous : y_previous - y;
        if (diff == 1)
          diff1count++;
      } while (diff > 1 || (diff == 1 && diff1count <= 1));
      y = (y_previous + y) / 2;
      return y;
    }