2

Arduino has been giving me unexpected values when trying to multiply numbers together in preprocessor.

e.g.

#define msPerDay (24 * 60 * 60 * 1000)
void setup() {
    Serial.begin(9600);
    Serial.println(msPerDay);
}
void loop() {}

This should output 86400000 but instead I get

23552

In the serial monitor. Also

#define msPerDay (60 * 1000)
void setup() {
    Serial.begin(9600);
    Serial.println(msPerDay);
}
void loop() {}

Should output 60000 but instead prints

-5536

Why is this giving me these unexpected values, what are the rules C++ uses to calculate #define multiplications?

Jail4Kale
  • 63
  • 1
  • 1
  • 7

2 Answers2

6

Your int is a 16 bit integer. A 16 bit integer holds values up to 2^15-1 if signed, and 2^16-1 if unsigned.

As those have no suffix, they are all ints, so overflow is undefined.

In practice, your compiler is doing math modulo 2^16.

Odds are that long on your platform is 32 bits. Append an l to those values. It is quite possible that Serial still won't print the value properly if it only prints ints. (It may have a long overload).

Another possibility is that Serial's print method is a 16 bit int and the truncation is going on there, but I doubt it.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • Thanks for the help. Does using longs in preprocesor affect memory usage of the actual program? Not sure why preprocessor wouldn't default to using the largest memory type. – Jail4Kale Aug 22 '21 at 07:18
  • 2
    The preprocessor, running on the host, might very well have used wider integers. But when that value was needed to generate the code for the Arduino, it truncated the value to 16 bits, since that is what an "int" is on the Uno. By marking one of the numbers a long, "24L", the code generator should know to generate a wider constant value. This page might help; also look at the page for 'long': https://www.arduino.cc/reference/en/language/variables/data-types/int/ – aMike Aug 22 '21 at 13:37
4

In binary 86400000 is 101001001100 101110000000000. To store this number you need 32 bits. But you store this number in 16 bits and you work with 101110000000000, it is 23552.

101001001100 101110000000000
             101110000000000
Wootiae
  • 728
  • 1
  • 7
  • 17