0

I have these 2 arrays:

     char *names[] = {"Marie","Pascale","Valarie","Juanita"};
     int ages[] = {35, 38, 42, 48};

     // this returns the number of elements in the int array
     int compte = sizeof(ages)/sizeof(int);

How do I get the number of elements in the char array?

thiebo
  • 1,339
  • 1
  • 17
  • 37
  • 3
    `sizeof names / sizeof *names`? And that's not a char array, its a `char *` array. – mediocrevegetable1 May 23 '21 at 12:06
  • 3
    The same way. `names` holds pointers which are of equal size. (It does *not* hold the char arrays themselves; apart from the fact that the syntax specifies the elements being `char *`, it is also for very principle reasons not possible to hold elements of varying sizes in arrays: The index expression `a[i]` translates to `*(a+i)`. Which, by the way, implies that `i[a]` is perfectly valid. Try it!) – Peter - Reinstate Monica May 23 '21 at 12:06
  • 1
    Does this answer your question? [How do I determine the size of my array in C?](https://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c) – Paul Hankin May 23 '21 at 12:10
  • Ah, if the question was how to express the size of a char pointer (as opposed to the size of an `int`, which you demonstrated that you know) it is simply `sizeof(char *)`. But mediocre has given you a more robust example using the first element of the array, which keeps working even if in the future you change the element type. – Peter - Reinstate Monica May 23 '21 at 12:12
  • Relying on `sizeof` to calc array elements will eventually bite you (especially using it inside a function in order to calc the length of the "array" passed in as a parameter). A safer approach is to either keep track of the length of your arrays and pass it along with arrays to functions if need be, or mark the end of your arrays with an extra sentinel value at the end, and then iterate over the array until you hit that sentinel value. – Harry K. May 23 '21 at 12:14

2 Answers2

2

Only indirectly because you have a terminating null byte instead of a saved size or a real array.

#include <string.h>
/*...*/
int c_names  = sizeof names / sizeof*names;
for (int i = 0; i < c_names; i++)
    printf("%zu %s %p\n", strlen(names[i]), names[i], names[i]);

This gives content-length, content and address (underef. content) of the char-pointers in names:

5 Marie 0x555c45587004
7 Pascale 0x555c4558700a
7 Valarie 0x555c45587012
7 Juanita 0x555c4558701a

Without getting too philosophical about arrays and pointers: This is a good illustration. Not possible to know where "Pascale" starts if "Marie" can have any length. "Marie" is space saving but bad for the alignment.


How do I get the number of elements in the char array?

By looping until you find a null byte aka strlen(). You did not really allocate any char array or terminate it, the compiler did, but you can safely READ the chars up to the \0.

For same reason (so called string literals) names could be const:

 printf("%c\n", names[2][0]); // OK prints 'V'
 names[2][0] = 'F';           // Segm. Fault 

So "char array" is misleading in this context. Arrays do not segfault when assigned to.

1

Since names is an array of pointers, it can be computed in the same way as with ages:

int num_names = sizeof(names) / sizeof(char *);

Furthermore, you can do this instead:

int num_names = sizeof(names) / sizeof(*names);

And the same for ages:

int compte = sizeof(ages) / sizeof(*ages);

If you instead meant the array pointed to by each elements of names, you can only do so indirectly, like @chezfilou mentions, using strlen.

Now, if you want to make it easier to deal with, you could use a struct, like so:

struct person {
    const char *name;
    unsigned age;
} persons[] = {
    {.name = "Marie",   .age = 35,},
    {.name = "Pascale", .age = 38,},
    {.name = "Valarie", .age = 42,},
    {.name = "Juanita", .age = 48,},
};
Ismael Luceno
  • 2,055
  • 15
  • 26