Uses for multiple levels of pointer dereferences?

Solution 1:

each star should be read as "which pointed to by a pointer" so

char *foo;

is "char which pointed to by a pointer foo". However

char *** foo;

is "char which pointed to by a pointer which is pointed to a pointer which is pointed to a pointer foo". Thus foo is a pointer. At that address is a second pointer. At the address pointed to by that is a third pointer. Dereferencing the third pointer results in a char. If that's all there is to it, its hard to make much of a case for that.

Its still possible to get some useful work done, though. Imagine we're writing a substitute for bash, or some other process control program. We want to manage our processes' invocations in an object oriented way...

struct invocation {
    char* command; // command to invoke the subprocess
    char* path; // path to executable
    char** env; // environment variables passed to the subprocess
    ...
}

But we want to do something fancy. We want to have a way to browse all of the different sets of environment variables as seen by each subprocess. to do that, we gather each set of env members from the invocation instances into an array env_list and pass it to the function that deals with that:

void browse_env(size_t envc, char*** env_list);

Solution 2:

If you work with "objects" in C, you probably have this:

struct customer {
    char *name;
    char *address;
    int id;
} typedef Customer;

If you want to create an object, you would do something like this:

Customer *customer = malloc(sizeof Customer);
// Initialise state.

We're using a pointer to a struct here because struct arguments are passed by value and we need to work with one object. (Also: Objective-C, an object-oriented wrapper language for C, uses internally but visibly pointers to structs.)

If I need to store multiple objects, I use an array:

Customer **customers = malloc(sizeof(Customer *) * 10);
int customerCount = 0;

Since an array variable in C points to the first item, I use a pointer… again. Now I have double pointers.

But now imagine I have a function which filters the array and returns a new one. But imagine it can't via the return mechanism because it must return an error code—my function accesses a database. I need to do it through a by-reference argument. This is my function's signature:

int filterRegisteredCustomers(Customer **unfilteredCustomers, Customer ***filteredCustomers, int unfilteredCount, int *filteredCount);

The function takes an array of customers and returns a reference to an array of customers (which are pointers to a struct). It also takes the number of customers and returns the number of filtered customers (again, by-reference argument).

I can call it this way:

Customer **result, int n = 0;
int errorCode = filterRegisteredCustomers(customers, &result, customerCount, &n);

I could go on imagining more situations… This one is without the typedef:

int fetchCustomerMatrix(struct customer ****outMatrix, int *rows, int *columns);

Obviously, I would be a horrible and/or sadistic developer to leave it that way. So, using:

typedef Customer *CustomerArray;
typedef CustomerArray *CustomerMatrix;

I can just do this:

int fetchCustomerMatrix(CustomerMatrix *outMatrix, int *rows, int *columns);

If your app is used in a hotel where you use a matrix per level, you'll probably need an array to a matrix:

int fetchHotel(struct customer *****hotel, int *rows, int *columns, int *levels);

Or just this:

typedef CustomerMatrix *Hotel;
int fetchHotel(Hotel *hotel, int *rows, int *columns, int *levels);

Don't get me even started on an array of hotels:

int fetchHotels(struct customer ******hotels, int *rows, int *columns, int *levels, int *hotels);

…arranged in a matrix (some kind of large hotel corporation?):

int fetchHotelMatrix(struct customer *******hotelMatrix, int *rows, int *columns, int *levels, int *hotelRows, int *hotelColumns);

What I'm trying to say is that you can imagine crazy applications for multiple indirections. Just make sure you use typedef if multi-pointers are a good idea and you decide to use them.

(Does this post count as an application for a SevenStarDeveloper?)