Most of the time I find for-loops only iterate a handful of times.
I've taken to using Byte or uint8_t as the iterator datatype as general practice.
The thinking being that we should care wherever possible about datatype size in embedded systems.
But is it possible there's no point doing this?
e.g would the compiler make Ints into Bytes anyway if it knows the upper limit from the loop definition?
Using a "uint8_t" on a 32-bit processor might require more code than a normal 32-bit "int".
When I write code for beginners, then I use more brackets '{' and '}' and I prefer "int" in a for-loop.
Suppose you have this:
int myArray[10];
for (uint8_t i=0; i<10; i++)
{
Serial.println(myArray[i]);
}
and then decide that you need the numbers in reverse:
int myArray[10];
for (uint8_t i=9; i>=0; i++) // bug
{
Serial.println(myArray[i]);
}
then you have a bug.
I think that a "int" in the source code is easier to read. The optimization for "uint8_t" is for a ATtiny or ATmega8. But there is no golden rule for this.
Yes int is more readable for sure, and if the compiler make the optimization in a smart way most of the time, then I think Int is probably the way to go.
I can't help but bring up the philosophical argument for code optimisation here.
Coming from Amiga 500 days where a crack group could crunch down 5 full games with gfx and audio assets onto a single 1.4mb floppy.
To today when e.g Apple's Numbers spreadsheet, a glorified table that does some math, containing no gfx or sound assets takes up ~580MB....
I can't help but think trends away from being memory footprint aware are starting to get out of hand.
I guess with SoC's getting cheaper with more ram and flash allows us to be sloppy.
...digression over...
and then decide that you need the numbers in reverse:
int myArray[10];
for (uint8_t i=9; i>=0; i++) // bug
{
Serial.println(myArray[I]);
}
Is this only a bug because though because it's still i++ instead of i--?
Nope. A uint will ALWAYS be greater than or equal to zero, so it's an infinite loop.
There are types int_fast8_t defined at the same time as uint8_t and etc. "use the fastest unsigned integer that is at least 8 bits wide." They should probably be used more often, but they're sort of ugly and hard to type
TBH I figured the point was to make an example that uints can't go negative.
But I'm confused by that particular example.
It would appear to me to start at 9 and (at least if it were using i--) decrement until it equals 0 and exit the loop, never encountering potential to go negative anyway.
Am I missing something?
Ok interesting.
So then, If I'm using an ESP32 variant or similar (increasingly common), then I guess I really should just use int then and let the compiler take care of it?
Does this then apply to all integers on a 32bit SoC?
Just use Int everywhere, even for small numbers?
Sorry, I meant "i--".
I should have tested it in Wokwi but I didn't
A down counting loop for an array stops at -1, so the loop variable must be signed.
Using Byte or uint8_t as the iterator datatype in for-loops is a good practice when working with embedded systems to save memory, as it's essential to be mindful of datatype sizes. However, it's important to note that modern compilers are generally quite efficient at optimizing code. If the compiler can determine that a loop's upper limit is small, it may automatically optimize the iterator to a smaller datatype, like uint8_t, even if you initially declared it as an int. So, while specifying the smaller datatype explicitly is a good practice for clarity and safety, the compiler might perform similar optimizations if it can infer the loop's characteristics. Nevertheless, it's a good habit to be explicit in your code to ensure you're using the appropriate datatype, especially in resource-constrained embedded systems.