Having seen some code examples on the Internet where sizeof should be used, I thought I'd offer a short reminder of a couple of useful cases:
1. A EPROM burner program to run on Arduino where the data was embedded as a byte array in the sketch which is then compiled and downloaded to run:
What was written:
const int progSize = 1024;
const byte hexProg[progSize] = { ... };
...
for (i = 0; i < progSize; i++) {
...
}
What should have been written:
const byte hexProg[] = { ... };
...
for (i = 0; i < sizeof(hexProg); i++) {
...
}
This has the advantage of automatically adapting to the number of bytes that actually need to be programmed instead of always 1024.
2. An Arduino program to test a LCD display:
What was written:
char row1[] = "I'm Arduino";
...
for (int positionCounter1 = 0; positionCounter1 < 26; positionCou
nter1++) {
This prints junk after the greeting because it strays past the end of the string, which is also a security hazard.
What should have been written:
for (int positionCounter1 = 0; positionCounter1 < sizeof(row1) - 1; positionCounter1++) {
The - 1 is to not print the NUL byte at the end of the string. A reminder, if the string is say UTF-8, sizeof gives the number of bytes in the string, not the number of characters. But usually the number of bytes is what you want.
Also do not make this mistake:
char *row1 = "I'm Arduino";
In this case sizeof(row1) will be sizeof(char *) on the machine, not the length of the phrase I'm Arduino.
A couple of other idioms.
Getting the number of elements in an array:
int divisors[] = { 2273, 2145, 2025, 1911, ... };
const int ndivisors = sizeof(divisors)/sizeof(int);
Or even better:
const int ndivisors = sizeof(divisors)/sizeof(divisors[0]);
which means you can change the type of the divisors array to be other than an int without changing the second line.
1. A EPROM burner program to run on Arduino where the data was embedded as a byte array in the sketch which is then compiled and downloaded to run:
What was written:
const int progSize = 1024;
const byte hexProg[progSize] = { ... };
...
for (i = 0; i < progSize; i++) {
...
}
What should have been written:
const byte hexProg[] = { ... };
...
for (i = 0; i < sizeof(hexProg); i++) {
...
}
This has the advantage of automatically adapting to the number of bytes that actually need to be programmed instead of always 1024.
2. An Arduino program to test a LCD display:
What was written:
char row1[] = "I'm Arduino";
...
for (int positionCounter1 = 0; positionCounter1 < 26; positionCou
nter1++) {
This prints junk after the greeting because it strays past the end of the string, which is also a security hazard.
What should have been written:
for (int positionCounter1 = 0; positionCounter1 < sizeof(row1) - 1; positionCounter1++) {
The - 1 is to not print the NUL byte at the end of the string. A reminder, if the string is say UTF-8, sizeof gives the number of bytes in the string, not the number of characters. But usually the number of bytes is what you want.
Also do not make this mistake:
char *row1 = "I'm Arduino";
In this case sizeof(row1) will be sizeof(char *) on the machine, not the length of the phrase I'm Arduino.
A couple of other idioms.
Getting the number of elements in an array:
int divisors[] = { 2273, 2145, 2025, 1911, ... };
const int ndivisors = sizeof(divisors)/sizeof(int);
Or even better:
const int ndivisors = sizeof(divisors)/sizeof(divisors[0]);
which means you can change the type of the divisors array to be other than an int without changing the second line.
Allocating the right amount of memory from heap:
double *readings;
...
readings = malloc(NREADINGS * sizeof(double));
And a reminder, sizeof is a compile-time operator, so there is no runtime cost to using it. If the expression provided to sizeof cannot be evaluated at compile-time, the compiler will tell you.
No comments:
Post a Comment