Size_t as function argument unexpected result

Hi everyone,

i have a function to check a timeout and i would like it to take two arguments of size_t (to be sure the biggest value of millis() will fit).
However when declaring the function with size_t arguments the code does no longer work. It compiles but it does nothing.

With arguments wrongPassTimestamp and wrongPassTimeout declared as unsigned long there are no problems.

const unsigned long wrongPassTimeout = 15000L;
unsigned long wrongPassTimestamp = 0L;

bool CheckPasswordTimeout(size_t wrongPassTimestamp, size_t wrongPassTimeout)
{
  if (millis() - wrongPassTimestamp < wrongPassTimeout)
    return true;
  else
    return false;
}

Can you please help me find out what am i missing?

This works fine:

bool CheckPasswordTimeout(unsigned long wrongPassTimestamp, unsigned long wrongPassTimeout)
{
  if (millis() - wrongPassTimestamp < wrongPassTimeout)
    return true;
  else
    return false;
}

The millis() function returns a "unsigned long", that is what you should use.

The size_t is for example for the number of array elements. It has no relation with millis(). Don't mix two worlds.

https://en.cppreference.com/w/cpp/types/size_t

std::size_t can store the maximum size of a theoretically possible object of any type (including array).

The bit width of std::size_t is not less than 16.

So on an Arduino platform, you'll actually have to dig pretty deep to figure out what size_t actually is (16 bit? 32?) and it will be platform-dependent.
Using size_t the way you're doing doesn't make sense.

By definition millis() outputs unsigned long, so you know what data type you need - no need to second-guess, wrap another layer of obfuscation around it etc.

Because the Arduino Uno has only a small SRAM, and therefor only 16 bit data pointers, its size_t is only 2 bytes.

void setup() 
{
  Serial.begin(9600);
  Serial.println( sizeof(size_t));
}

void loop() {}

Yeah, but port the same code to ESP32 and I bet it wil be 4 bytes...so due to this 'black box behavior' it's not a good choice.

size_t is a type that can hold the maximum size of an object (like an array or struct), and has nothing to do with the size of a particular variable, or the milliseconds values used in Arduino. So on an AVR, the maximum size of an array is 32768 bytes, which fits in a 2-byte "unsigned int", and size_t is equivalent to uint16_t.

millis() in Arduino is defined to return uint32_t (on any platform) (that's 4 bytes, far less than the 32k max size of an object.)

Even if not related to the problem, you are aware that the function could be a one liner?

bool CheckPasswordTimeout(unsigned long wrongPassTimestamp, unsigned long wrongPassTimeout)
{
  return (millis() - wrongPassTimestamp < wrongPassTimeout);
}

That makes things clear, thank you.
@Danois90 now I do :slight_smile:

Why would you say that ? It is defined as "unsigned long".

Reference: Data type: unsigned long

AVR core: unsigned long

Arduino API: unsigned long

SAMD core: unsigned long

I see many times that others declare a uint32_t variable to be used with millis(). I don't like that, there is no need for it. Its purpose seems to be to make it more interesting as if that makes it better. I think it is not needed.

Arduino 101 is an oddball with uint64_t millis() and micros().

1 Like

It matters less what the return type of millis() and micros() are. What matters more are the (unsigned) data types used to store the return value: 8 bit is sufficient for timing <= 255 ms/µs, 16 bit is sufficient for timing <= 65.5 sec/ms and so on.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.