Reputation: 1216
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
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