1

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.

  • Can you give an example please? eg. char foo [100] = "bar"; - is that what you mean? You want the answer: 3? – Nick Gammon Jul 12 '15 at 0:33
  • yes that's right – Federico Corazza Jul 12 '15 at 0:34
10

You want strlen.

char foo [100] = "bar";
Serial.println (strlen (foo));   // --> prints 3
  • If the answer worked for you please click the "accept" button (it looks like a tick). That way other people will know that the solution worked. – Nick Gammon Jul 12 '15 at 0:53
  • I had to wait a couple of minutes to do that – Federico Corazza Jul 12 '15 at 0:57
  • Note that this will only work if the data in your 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
  • Quite right. My answer was for the question as presented. The things you mention should be taken into account for null-terminated C strings. – Nick Gammon Jul 12 '15 at 2:20
3

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:

  1. calls println(message)
  2. which calls write(message)
  3. which gets the string length with strlen(message)
  4. and calls write(message, length)
  5. which then loops from 0 to length-1 sending each character of message to write() in turn.
  6. finally prints the \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...

  • Re “In its simplest form the strlen() function might look like this”, in a shorter (perhaps simpler?) form it could look like: int strlen(const char *data) { const char *p = data; while (*p++); return p-data-1; } – James Waldby - jwpat7 Jul 12 '15 at 16:27
  • @jwpat7 I said "simplest", not "shortest and most compact". That form, while smaller and more efficient, is much much harder for the OP (who is obviously not a programmer) to understand. – Majenko Jul 12 '15 at 16:29
  • Agreed :) Also easier to make mistakes in. And if the \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
  • Actually, *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
  • It is a compile-time macro ... It's not a macro, it's an operator (like "+" and "-" are operators). They are lower-level than macros which are things done at pre-processor time. See sizeof operator. Also Operators in C++ – Nick Gammon May 14 '18 at 7:05
-4
use sizeof 

char nnn[10];
for(int i=0; i< sizeof(nnn)/sizeof(char); i++){

}


  • 3
    Did you properly read the question? – gre_gor Feb 28 '18 at 21:00
  • The OP said sizeof "doesn't work for me" and then you suggest using sizeof. – Nick Gammon May 14 '18 at 7:01
  • can;t answer the question when using the same unknown – Guy . D Feb 23 at 18:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.