If you learn about the spiral/clockwise rule you could decipher it as an array of 20 pointers to char
. I.e. an array of strings.
Depending on where the definition it, each element will either be null pointers (if it's a global variable) or each element will be uninitialized and have an indeterminate value (if s_item
is a local variable). Either way, you must make each pointer in the array point to some valid data before you can really use them, either by making them point to existing strings or by allocating memory dynamically which you then initialize.
As for a pointer to a pointer, it's just the same as any other pointer: It's a pointer that points to something, in this case it's pointing to another pointer.
Example:
char *p = malloc(12); // Allocate 12 bytes and make the variable p point to it
strcpy(p, "hello world"); // Initialize the memory we just allocated with a string
char **pp = &p; // Make the variable pp a pointer, and make it point to the variable p
In memory it looks something like this
+----+ +---+ +---------------+
| pp | --> | p | --> | "hello world" |
+----+ +---+ +---------------+
That is, pp
is pointing to the variable p
, and p
is pointing to memory containing the string "hello world"
.
The example shown above, having pp
is pretty much useless, but with pointers to pointers you can emulate pass by reference with function arguments, and for example do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function(char **pp)
{
*pp = malloc(12); // Allocate memory
strcpy(*pp, "hello world");
}
int main(void)
{
char *p; // Define variable, but don't initialize it
function(&p); // Pass a pointer to the variable p
printf("p = \"%s\"\n", p); // Will print p = "hello world"
}
By passing the pointer to the variable p
(using &p
) to the function, the function can modify the pointer (i.e. the value of p
).
Another use for pointer to pointer is dynamic array of arrays. For example
char **pp = malloc(5 * sizeof(char *)); // Allocate space for five pointers to char
for (size_t i = 0; i < 5; ++i)
{
pp[i] = malloc(12); // Allocate space for a string
strcpy(pp[i], "hello world"); // Initialize the memory
}
Now we have a dynamically allocated array of five dynamically allocated arrays of 12 characters.
Both uses of pointers to pointers works with other data-types than char
of course.
It should be noted that even though arrays naturally decays to a pointer to its first element, an array of arrays (like e.g. char x[20][20]
) is not the same as a pointer to pointer (e.g. char **
). For an explanation of this see e.g. this old answer of mine.