This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Overflow handling in C

Hello to all.
Please excuse my naive question, but to me it's a real problem.
I want to add to signed nummber's.
If an overflow occurs the sign is changed unwanted!
Don't like it, better the result is limited and the sign doesn't change
Here is my solution:

 signed long int a,b,c;

//some AD-Converting stuff

  a = b + c;
  if (a<0 && b>0 && c>0) a=0x7FFFFFFF;
  if (a>=0 && b<0 && c<0) a=0x80000000;


Maybe this will work.
But can i be sure that it will work under any circumstances?
Is it a good solution?
Or will it consume lot of recources? (cause there in the IF statements is a lot of comparation to do)

How can i manage this similar case when i want to add a nummber a to b:

 signed long int a,b;

//some AD-Converting stuff

  a += b;

Ones again i want to excause myself i'am no native english speaker and i have only very little experience in programming C :-)

Parents
  • If an overflow occurs the sign is changed unwanted!

    Actually, overflow of computations in signed numbers causes undefined behaviour. A change of sign would be among your lesser worries there. Usually you get wrap-around arithmetic (and yes, that does include a change of sign), but you're not supposed to bet on it.

    What you seem to be looking for is usually called a saturated arithmetic operator. It's one of several way of approaching the fundamental differences between finite arithmetic on computers and the arithmetic of potentially infinite numbers we all learn in school.

    But because the result of overflow, once you allow it to happen, is formally undefined, no test on the result can possibly fix it. You have to test your inputs before you perform the operation.

    Safely implementing such tests for the largest supported integer type usually involves comparing the operands with appropriately constructed values built using the MIN and MAX macros from <limits.h>. Something roughly like this:

    if (a < 0) {
      if (b < 0) {
        /* two negatives, possible overflow downward */
        if (b < (LONG_MIN - a))
           return LONG_MIN;
        else
           return a + b;
      } else {
        return a + b;
      }
    } else {
      /* filling out the other half is left as an exercise to the reader...*/
    }
    

    For smaller types, you just go via bigger types, i.e. you do the computation in the next bigger type, then check the result before you assign it back to the real result:

    short saturated_add_shorts(short a, short b)
    {
       long temp = (long)a + (long)b;
    
       if (temp > (long)SHRT_MAX)
          return SHRT_MAX;
       else if (temp < (long)SHRT_MIN)
          return SHRT_MIN;
       else
          return (short)temp;
    }
    

    And yes, such tests are costly. But then again, so is any operation on long integers on a small 8-bitter like this.

Reply
  • If an overflow occurs the sign is changed unwanted!

    Actually, overflow of computations in signed numbers causes undefined behaviour. A change of sign would be among your lesser worries there. Usually you get wrap-around arithmetic (and yes, that does include a change of sign), but you're not supposed to bet on it.

    What you seem to be looking for is usually called a saturated arithmetic operator. It's one of several way of approaching the fundamental differences between finite arithmetic on computers and the arithmetic of potentially infinite numbers we all learn in school.

    But because the result of overflow, once you allow it to happen, is formally undefined, no test on the result can possibly fix it. You have to test your inputs before you perform the operation.

    Safely implementing such tests for the largest supported integer type usually involves comparing the operands with appropriately constructed values built using the MIN and MAX macros from <limits.h>. Something roughly like this:

    if (a < 0) {
      if (b < 0) {
        /* two negatives, possible overflow downward */
        if (b < (LONG_MIN - a))
           return LONG_MIN;
        else
           return a + b;
      } else {
        return a + b;
      }
    } else {
      /* filling out the other half is left as an exercise to the reader...*/
    }
    

    For smaller types, you just go via bigger types, i.e. you do the computation in the next bigger type, then check the result before you assign it back to the real result:

    short saturated_add_shorts(short a, short b)
    {
       long temp = (long)a + (long)b;
    
       if (temp > (long)SHRT_MAX)
          return SHRT_MAX;
       else if (temp < (long)SHRT_MIN)
          return SHRT_MIN;
       else
          return (short)temp;
    }
    

    And yes, such tests are costly. But then again, so is any operation on long integers on a small 8-bitter like this.

Children
No data