The reason you can print strings in main() but not in print_array is the result of how an array is converted to a pointer on access. What this means is that when you access an array (subject to 4 exceptions below) the array is converted to a pointer to the first element in the array. After the conversion takes place, as it does when you pass an array as a parameter to a function, you have only a pointer, not an array.
The C11 Standard (as well as the C17 Standard) reads as follows:
Array pointer conversion
(p3) Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary '&' operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue.
C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
If you note above, when used with the sizeof operator, and array is not converted to a pointer, so in main(), sizeof(strings) / sizeof(strings[0]) provides the number of elements in the array of string. However, after you pass strings to print_array, the conversion to pointer has already occurred, so that in print_array your attempted use of sizeof results in:
size_t array_length = sizeof(a_pointer) / sizeof(a_char);
(which is 8 on x86_64, or 4 on x86)
You have two choices (1) pass the number of elements in your array as a second parameter to print_array, or (2) make the last pointers in strings NULL (to be used as a sentinel value). Then in print_array you can just iterate over strings[i] until it is NULL.
A couple of quick examples:
Passing the Number of Elements
#include <stdio.h>
void print_array (char **strings, size_t nptrs)
{
for (size_t i = 0; i < nptrs; i++)
printf("%s, ", strings[i]);
putchar ('\n');
}
int main(void) {
char *strings[] = { "Hello",
"Zerotom",
"new" };
print_array (strings, sizeof strings/sizeof *strings);
return 0;
}
Example Use/Output
$ ./bin/prnarray
Hello, Zerotom, new,
Adding a Sentinel NULL to strings
#include <stdio.h>
void print_array (char **strings)
{
for (size_t i = 0; strings[i]; i++)
printf("%s, ", strings[i]);
putchar ('\n');
}
int main(void) {
char *strings[] = { "Hello",
"Zerotom",
"new",
NULL }; /* sentinel NULL */
print_array (strings);
return 0;
}
(same output)
There are at least a handful of ways to loop using either for or while loops and either using a pointer to strings and pointer arithmetic, or using array indexing (the difference are simple semantics as you are doing the same thing). Look things over and let me know if you have further questions.
void print_array (char **strings)and you must pass thenumberof strings to the function (or use a sentinelNULLto mark the end of valid strings)size_t array_length = sizeof(strings) / sizeof(strings[0]);does NOT work after the array is passed as a parameter to a function (it is converted to a pointer) so you in effect havesize_t array_length = sizeof(a_pointer) / sizeof(a_char);sizeofoperator (but that must be within the scope in which the array was declared). After being passed as a parameter, it is just a pointer. See C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)string, is not the same in the 2 cases, Withchar * strings[],stringsis not an array...., "new", NULL. Then you can passstringsto the function and dowhile (*strings != NULL) printf("%s, ", *strings++);orsize_t i = 0; while (strings[i] != NULL) printf("%s, ", strings[i++]);Or, if you preferforloops thenfor (size_t i = 0; strings[i]; i++) { ... }