Millis() with int

I am using this code to print out on a serial monitor at a particular interval. I don't understand why the code works in the -ve values.

millis() gives unsigned long, however, I am curious why the if statement works in the -ve values.

int ct, pt = 0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  ct = millis();
  if (ct - pt > 1000) {
    Serial.print("ct: ");
    Serial.print(ct);
    Serial.print("\tpt: ");

    Serial.println(pt);
    pt = ct;
  }
}

The output is in the image.
ct - current time
pt - previous time

1

because the code has not exceeded the limits of an int, yet.

if ct = -31908 and pt = 32627 is considered. The if statement

if (ct - pt > 1000)

still works. Why?

(-31908)-32627= 719 is a legitimate math problem that does not exceeded the limits of the declared variables. An int is both + and - a unsigned int is intended for positive numbers only.

What problem are you having with the numbers?

You can make yourself a "tiny millis timestamp" that can handle overflow just like its 'unsigned long' brother. Example:

unsigned int littleNow = millis()

subsequently, you can safely do things like:

unsigned int lastLittleNow;
...
if (littleNow - lastLittleNow >= interval) { ...

with the restriction than 'interval' can be no longer than 65535ms

To see how (-31908) - (32627) works in 16 bits we first convert the numbers to hexadecimal:
0x835C - 0x7F73
We change that to an addition problem by changing it to:
0x835C + (-0x7F73)
To negate 0x7F73 we invert the bits and add 1 (2's Complement)
0x835C + 0x808D
The result of the addition is: 0x103E9 (66537) but that gets truncated to 16 bits so the actual result is:
0x03E9 = 1001 which is greater than 1000.

2 Likes