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 struct
s.)
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?)