Addition overflow

Hi,

I have a doubt whit the addition instruction and know if an overflow happened.

uint8_t a = 200;
uint8_t b = 200;

uint8_t c = a + b; // the sum is overflowed

// c is 200 + 200 = 400 >>> 400 - 255 = 145

I can tell if the sum is overflowed.

In ASM normally I have the carry bit to know that. In C and in Arduino, can I use a instruction, flag or something similar?

Thanks.

leonelpepe:
In C and in Arduino, can I use a instruction, flag or something similar?

No, there's nothing like that.

OK, it is a very bad news. The only way that I can tinks is that c must be greather than a and b at the same time:

uint8_t a = 200;
uint8_t b = 200;

uint8_t c = a + b; // the sum is overloaded

// c is 200 + 200 = 400 >>> 400 - 255 = 145

if (c < a && c < b) {
  // Overload have being success.
}

I think you're referring to 'overflow' not overload.

lloyddean:
I think you're referring to 'overflow' not overload.

mmm. Yes, I'm not speak English very well. Sorry.

Give this a try...

bool SafeAdd( uint8_t a, uint8_t b, uint8_t & r )
{
  uint16_t t;
  
  t = a + b;
  
  r = t;
  
  return( (t & 0xFF00) == 0 );
}

bool SafeAdd( uint16_t a, uint16_t b, uint16_t & r )
{
  uint32_t t;
  
  t = a + b;
  
  r = t;
  
  return( (t & 0xFFFF0000) == 0 );
}

void Test1( void )
{
  uint8_t a = 200;
  uint8_t b = 200;
  uint8_t r;

  if ( SafeAdd( a, b, r ) )
  {
    Serial.println( F( "No problem." ) );
  }
  else
  {
    Serial.println( F( "Bad news!" ) );
  }
}

void Test2( void )
{
  uint8_t a = 200;
  uint16_t b = 200;
  uint16_t r;

  if ( SafeAdd( a, b, r ) )
  {
    Serial.println( F( "No problem." ) );
  }
  else
  {
    Serial.println( F( "Bad news!" ) );
  }
}

void setup( void )
{
  Serial.begin( 250000 );
  
  Test1();
  Test2();
}

void loop( void )
{
}
1 Like

It is a great idea. Thanks, but... if I want to use a 32 bit variable? jaja

Then you use uint64_t for the result.

I think, but am not sure, you can access the microcontroller "status register" from C code.

I think in "Arduino C" there is a special variable called "SREG" which is a representation of the status register of the microcontroller. The microcontroller status register contains a collection of flags and one of those flags is the carry flag. I think the carry flag is the flag in the status register bit0 .

You could try something like this:

boolean isCarryOverflow()
{
return(SREG & 0x01); //Assuming the carry flag in on bit0
}

void setup()
{
...
...
c = a + b;
if(isCarryOverflow)
{
...
}
...
}

ATmega datasheet >> http://www.atmel.com/Images/doc8161.pdf (page 10)
http://www.wvshare.com/article/AVR-1-1-5.htm

You can download the datasheet of your Arduino microcontroller from arduino.cc >> Products

• Bit 0 – C: Carry Flag
The Carry Flag C indicates a carry in an arithmetic or logic operation. See the “Instruction Set
Description” for detailed information.

Yeah its bit 0, there is also an instruction 'BSET' for checking bits in the status register.

leonelpepe:
Hi,

I have a doubt whit the addition instruction and know if an overflow happened.

uint8_t a = 200;
uint8_t b = 200;

uint8_t c = a + b; // the sum is overflowed

An unsigned 8 bit INT can only hold a value from 0 to 255 (decimal). If you add one to 255, it "rolls over" back to zero.

You need to use a larger INT... maybe a uint16_t (16 bits - 0 to 65535) or a uint32_t (32 bits - 0 to 4294967295) or even a uint64_t (64 bits.... ginormous!)

You can detect if a variable has overflowed. There is no carry bit available to C, but if the result is smaller than you expect, you can assume that an overflow has occurred.

Note that this is also true with subtraction... a uint8_t with a value of 0, minus 1 = 255. In this case, the result is larger than you expect and this signifies a borrow.

Mitxel:
I think, but am not sure, you can access the microcontroller "status register" from C code.

You can but doing so is "dangerous". The compiler can reorder (or even remove) code when it optimizes. When you write this...

c = a + b;
if(isCarryOverflow())
{
...
}
// Some code after the if that has no dependency on anything above.

The compiler could do something like this...

c = a + b;
// Some code that was after the if that has no dependency on anything nearby.
if(isCarryOverflow())
{
...
}

In other words, there is no way to guarantee the SREG check is performed immediately after the addition.

Yes, the compiler optimizer is always surprising.

This guy (Catching Integer Overflows in C) says that if an addtion of integers owerflowed, then the sum is always less than either addend. (I do not know the reason)

Then, say, we have A which is an integer of 48 bits, consisting A_Hi (16 bits) and A_Low (32 bits) and we add B which is a 32-bit integer.

Maybe something like that would work

unsigned int A_Hi;
unsigned long A_Low;
unsigned long B;

A_Low += B;
if(B > A_Low) A_Hi ++;

(I apologize for my horrid English)

Mitxel:
This guy (Catching Integer Overflows in C) says that if an addtion of integers owerflowed, then the sum is always less than either addend. (I do not know the reason)

I haven't followed that link, but I expect you meant to say that at least one of the addends will be greater than the sum (they may not both be greater).

I haven't followed that link, but I expect you meant to say that at least one of the addends will be greater than the sum (they may not both be greater).

if a <=255 and b<=255 and a+b > 255 ==> (a+b)%256 < a and (a+b)%256 < b

you can test this quite simple

void setup()
{
  Serial.begin(115200);
  for (uint8_t a = 0; a < 255; a++) // 255 not in the loop to prevent endless loop
    for (uint8_t b = 0; b < 255; b++)
    {
      uint8_t c = a + b;
      uint16_t d = (uint16_t )a + b;
      Serial.print((int)a);
      Serial.print('\t');
      Serial.print((int)b);
      Serial.print('\t');
      Serial.print((int)c);
      Serial.print('\t');
      Serial.print(c < a?"overflow":"ok");
      Serial.println();
    }
}
void loop(){}

but you can test overflow before it occurs just by doing a subtraction, no need to test a register, works for 16, 32 and 64 bit

void setup()
{
  Serial.begin(115200);
  for (uint8_t a = 0; a < 255; a++)
    for (uint8_t b = 0; b < 255; b++)
    {
      if (255 - b < a ) Serial.println("overflow");
      else Serial.println((int)(a+b));
    }
}
void loop(){}

I will try to access the carry bit in the status register. If i make a subtraction, it take so time, is a slowly solution. I don't want to avoid a overflow, I just want to know if a overfow have been curred.

I will try to access the carry bit in the status register. If i make a subtraction, it take so time, is a slowly solution. I don't want to avoid a overflow, I just want to know if a overfow have been curred.

What is the performance you need?
What are you trying to accomplish? goal of your project?

It is for a PLC (industrial controls). The performance it's not critical in this think, but the project is BIG and I prefer a cleaner code.

The name of the project is OpenMolo

The site of the project (in Spanish only) is:

http://libre.backupnet.com.ar/I1159-Open+Molo

And the documentation (in Spanish too) is:

http://repositorio.libre.backupnet.com.ar/OpenMolo/OpenMoloDOC/html/index.html

SVN: svn://svn.backupnet.com.ar/OpenMolo