caution: computations with constants

Hi,
when you do computations with constant values some precautions are needed.
A function to compute a date number from a date record initially got false results on an Arduino Nano:

unsigned long datenum(int ee_adr) {
  return( EEPROM[ee_adr+9] + EEPROM[ee_adr+8]*10 +        // Minuten
         (EEPROM[ee_adr+7] + EEPROM[ee_adr+6]*10)*60 +    // Stunden
         (EEPROM[ee_adr+5] + EEPROM[ee_adr+4]*10)*1440 +  // Tage
         (EEPROM[ee_adr+3] + EEPROM[ee_adr+2]*10)*44640 + // Monate
         (EEPROM[ee_adr+1] + EEPROM[ee_adr]*10)*535680 ); // Jahre
}

The date is stored in EEPROM with format yymmddHHMM (y:year, m:month, d:day, H:hour, M:minute).
ee_adr is pointing to the first byte of yy.
I expected that the compiler generates code to do all computations with 32bit, because the result is defined as unsigned long.

The multiplications for month and year have to be changed like the following code:

unsigned long datenum(int ee_adr) {
  return( EEPROM[ee_adr+9] + EEPROM[ee_adr+8]*10 +        // Minuten
         (EEPROM[ee_adr+7] + EEPROM[ee_adr+6]*10)*60 +    // Stunden
         (EEPROM[ee_adr+5] + EEPROM[ee_adr+4]*10)*1440 +  // Tage
         (EEPROM[ee_adr+3] + EEPROM[ee_adr+2]*10)*long(44640) + // Monate
         (EEPROM[ee_adr+1] + EEPROM[ee_adr]*10)*long(535680) ); // Jahre
}

When a constant, here 44640, can be represented by 16 bits then the computation is performed 16 bits wide only even if the result shall be unsigned long.
This is worth to know.

Apply a ‘UL’ to the constant to force the compiler to do math using ‘unsigned long’.

44640UL

SupArdu:
When a constant, here 44640, can be represented by 16 bits then the computation is performed 16 bits wide only even if the result shall be unsigned long.

computations as are done in variable type within the computation which is of the highest accuracy (or bit size) The result is not considered part of the computation. when doing computations between variables of signed & unsigned types the result can be unexpected. For variables casting is very important for instance

byte aByte=124;
byte bByte=65;
byte cByte=(((unsigned int) aByte)*255)/bByte;

forces a 16-bit calculation.

The default int type for the ATmega is 16 bit, you must always ensure casting or contagion is
used if you want 32 bit integers.

"Contagion" is when the result of an operator is widened to the size of its operands,
"casting" is when you declared explicitly the type.

The thing that confuses people is that integer constants by default have the default int type, whether
or not their value fits in that many bits. This is one of C's many rough edges.

Turn on compiler warnings, and read them...