Arduino variable overflow doesn't make sense - Page 1
Forum section: electronics / general

author: kuzm1nsk1
author_rank: Contributor
timestamp: March 29, 2024, 09:38:16 pm
content: This is just a demonstration code for what is happening. If I set:Code:uint32_t hour, minute, second;to:Code:uint8_t hour, minute, secondor:Code:int16_t hour, minute, second;or basically any data type that has range up to 32767, counter overflows after 32767 and jumps to 4294934528 which doesn't make any sense to me. Why should variables: hour, minute or second be larger than 1 byte if they only store numbers up to 60? Tested on original Arduino Uno and Nano Every.Code:#include <Wire.h>#include <DS3231.h>uint32_t counter = 0;uint32_t hour, minute, second;DS3231 clock;RTCDateTime dt;void setup() {Serial.begin(9600);clock.begin();clock.setDateTime(2024, 3, 29, 9, 6, 0);}void loop() {dt = clock.getDateTime();hour = dt.hour;minute = dt.minute;second = dt.second;Serial.print("Hour: ");Serial.print(hour);Serial.print("\tMinute: ");Serial.print(minute);Serial.print("\tSecond: ");Serial.print(second);counter = hour * 3600 + minute * 60 + second;Serial.print("\tCounter: ");Serial.println(counter);delay(1000);}Serial monitor:Hour: 9 Minute: 6 Second: 0 Counter: 32760Hour: 9 Minute: 6 Second: 1 Counter: 32761Hour: 9 Minute: 6 Second: 2 Counter: 32762Hour: 9 Minute: 6 Second: 3 Counter: 32763Hour: 9 Minute: 6 Second: 4 Counter: 32764Hour: 9 Minute: 6 Second: 5 Counter: 32765Hour: 9 Minute: 6 Second: 6 Counter: 32766Hour: 9 Minute: 6 Second: 7 Counter: 32767Hour: 9 Minute: 6 Second: 8 Counter: 4294934528Hour: 9 Minute: 6 Second: 9 Counter: 4294934529Hour: 9 Minute: 6 Second: 10 Counter: 4294934530Hour: 9 Minute: 6 Second: 11 Counter: 4294934531Hour: 9 Minute: 6 Second: 12 Counter: 4294934532Hour: 9 Minute: 6 Second: 13 Counter: 4294934533Hour: 9 Minute: 6 Second: 14 Counter: 4294934534Hour: 9 Minute: 6 Second: 15 Counter: 4294934535

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 29, 2024, 09:46:25 pm
content: It's due to the integer promotion rule.

author: kuzm1nsk1
author_rank: Contributor
timestamp: March 29, 2024, 09:50:44 pm
content: Is there a way to solve this because I'm using other library with functions that have parameters with size of one byte?

author: ejeffrey
author_rank: Super Contributor
timestamp: March 29, 2024, 11:58:17 pm
content: Code:counter = hour * 3600UL + minute * 60 + second;orCode:counter = (uint32_t) hour * 3600 + minute * 60 + second;Essentially: hour * 3600 can overflow, so one of the arguments (either one) needs to be cast to a 32 bit word before multiplication. Once you do that, the additions get promoted to 32-bits as well, so they won't overflow. The minute and second multiplications themselves should not overflow, so they don't need to be promoted.The former code depends on "long" being 32 bit, which is true on arduino.

author: NorthGuy
author_rank: Super Contributor
timestamp: March 31, 2024, 03:50:46 pm
content: Integer promotion has helped you a bit by converting the smaller types to integers before performing operations, but if integers are 16-bit long, it is not enough. Hence, you need to explicitly cast to 32-bit.

author: DavidAlfa
author_rank: Super Contributor
timestamp: March 31, 2024, 04:12:41 pm
content: Code:counter = hour * 3600 + minute * 60 + second;Think twice, hour is int16, so 9*3600 + 6*60 + 15 = 32775, but the largest value it can hold is 32767.It overflows during the calculation, before the result is transfered to counter.You can specify the compiler to convert hour into int32 when making calculations like ejeffrey said.This way you can keep hour, minute and second as int8.Before using a random integer size, check the largest value it can hold.In your case it's 23h 59min 59s = 86.399. You definitely need int32 for calculation.