What kind of function can I use to know how many elements are in an array char?
sizeof() gives the number of 'spaces' available so it doesn't work for me.
Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. It only takes a minute to sign up.
Sign up to join this communityWhat kind of function can I use to know how many elements are in an array char?
sizeof() gives the number of 'spaces' available so it doesn't work for me.
You want strlen
.
char foo [100] = "bar";
Serial.println (strlen (foo)); // --> prints 3
char[]
contains an ascii string, and is properly null-terminated. Furthermore, if you have a long string in the char[]
, and you overwrite it with a shorter string without adding the null-termination, you will get the size of the older string.
– Connor Wolf
Jul 12 '15 at 1:54
I know you have your answer from @NickGammon, but I'd just like to add a bit more in-depth information about how all this works.
sizeof()
is not a function in the normal sense of the word. It is an operator which gives you the number of bytes of memory allocated to whatever you pass to it. If you pass it an array then it returns the number of bytes that array has available to it. If you pass it a pointer to an array then it returns the size of that pointer, not the size of the array. If you pass it an integer variable it returns the number of bytes used by that integer variable (2 on an 8-bit system like AVR, 4 on a 32-bit system like the Due).
So some examples:
char array[50] = "hello";
// sizeof(array) = 50.
char *array_p = array;
// sizeof(array_p) = 2 or 4 depending on architecture.
char single = 'a';
// sizeof(single) = 1.
char string[] = "hello";
// sizeof(string) = 6 (5 letters plus \0) - it allocates the memory at compile time to fit the string
Now strlen()
. How exactly does that differ from sizeof()
? Simply put, strlen()
counts the number of characters in a character array up until it reaches the character \0
which is the "NULL" terminating character of a C string. Let's take the examples before but use strlen instead:
char array[50] = "hello";
// strlen(array) = 5.
char *array_p = array;
// strlen(array_p) = 5.
char single = 'a';
// strlen(single) = ERROR! strlen() doesn't operate on single characters.
char string[] = "hello";
// strlen(string) = 5.
You notice it always returns the number of characters in the string up to, but not including, the trailing \0
character.
In its simplest form the strlen()
function might look like this:
int strlen(const char *data) {
int c = 0;
const char *p = data;
while (*p) {
c++;
p++;
}
return c;
}
Basically it starts at the first character in the string (*p = data
), examines if it's a \0
or not (while (*p)
), increments the count of characters (c++
) and moves on to the next character in the string (p++
).
If you want to iterate through your string in your program you could call strlen()
first to get the number of characters in the string then use that value in a loop. That is a bit wasteful, since strlen()
first iterates through the string, so you end up iterating through it twice. It is far more efficient to learn how best to step through each character in the string until you find the terminating character, such as how the strlen()
function uses the pointer to move through memory. You can also see just how vital it is that you ensure the \0
character exists at the end of the string, otherwise how will functions like strlen()
know when to stop? They can't know how long the string is (sizeof()
will return the size of the pointer it is passed, not the size of the array), so they have to have some kind of manual marker, and the convention in C is to use \0
.
Note that Arduino's print()
functions actually do it very inefficiently. If you do something like:
char message[] = "Hello";
Serial.println(message);
It will actually do quite a lot of work it doesn't really need to. Taken step by step it:
\r\n
for the new-line.So it actually ends nested around 4 functions deep, and iterates the entire string twice. A classic example of how to waste processing time. By iterating through the string once looking for the \0
character in the write(message)
function (step 2) it would operate at least twice as fast. Good old Arduino...
int strlen(const char *data) { const char *p = data; while (*p++); return p-data-1; }
– James Waldby - jwpat7
Jul 12 '15 at 16:27
\0
is the last accessible byte in a segment, the *p++
will fault. But int strlen(const char *data) { const char *p = data; while (*p) ++p; return p-data; }
avoids that problem.
– James Waldby - jwpat7
Jul 12 '15 at 16:30
*p++
won't fault even if the \0
is the last accessible byte in a segment; the *p
part will access the last byte; the ++ part will set p
to an invalid address; but as that invalid address doesn't get referenced, on a typical machine no fault occurs.
– James Waldby - jwpat7
Jul 12 '15 at 16:38
use sizeof char nnn[10]; for(int i=0; i< sizeof(nnn)/sizeof(char); i++){ }
sizeof
"doesn't work for me" and then you suggest using sizeof.
– Nick Gammon♦
May 14 '18 at 7:01
char foo [100] = "bar";
- is that what you mean? You want the answer: 3? – Nick Gammon♦ Jul 12 '15 at 0:33