Combinatix
Combinatix

Reputation: 1216

Multiplying within #define gives strange values

I write a code for Arduino Nano and I experience this weird behaviour:

#define     GREAT      (60 * 60000)
#define     STRANGE     (60 * 6000)
#define     ZERO_X      (60 * 1000)

void setup() {
    Serial.begin(115200);
    Serial.println(GREAT);      // Prints 3600000, that's correct
    Serial.println(STRANGE);    // Prints 32320, thats wrong
    long zerox = ZERO_X;
    Serial.println(zerox);      // Prints -5536, thats also wrong, obviously
}

void loop() {}

What is going on?

I use MSVS2019 Comunity with vMicro

Upvotes: 0

Views: 144

Answers (1)

Slava
Slava

Reputation: 44268

You use integer literals to define your values, and as described in documentation type of literal depends on where it can fit. According to specs

On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value.

(emphasis is mine) Arduino Nano has CPU with 2 bytes int - 60, 6000 and 1000 fit in signed integer and such type is used. Though neither values of 60 * 6000 nor 60 * 1000 can fit in 2 bytes int so you get integer overflow with UB and unexpected values.

On another side 60000 does not fit into signed int of 2 bytes, so it gets type long with 4 bytes and 60000 * 60 fits there so you get expected result. To fix your problem you can just specify suffixes:

#define     GREAT      (60 * 60000L)
#define     STRANGE     (60 * 6000L)
#define     ZERO_X      (60 * 1000L)

and force them all to be type long. It is not necessary to do it for 60000, but it is better to have it for consistency.

For your code change:

long zerox = ZERO_X;

this line does not solve the issue as after macro substitution it is equal to:

long zerox = (60 * 1000);

and it does not help, as first calculations with type int are done on the right side of initialization, overflow happens and then int is promoted to long. To fix it you need to convert to long one of the arguments:

 long zerox = 60 * static_cast<long>(1000);

or use suffix as suggested before.

Upvotes: 5

Related Questions