One of the things I like about researching the C programming language is that many of the books written on the subject were authored by mathematicians and computer scientists who learned to program on early computing platforms where memory and CPU cycles were limited and expensive. Out of necessity, they learned to write programs that performed their tasks with the smallest footprint possible. This early experience bleeds in to their books, often resulting in a wonderful source of succinct and efficient coding examples, even if the author did not intend to convey that lesson.

Recently I investigated one of these gems from the book “C Interfaces and Implementations”, by David R Hansen, published in the 90s.

On page 109, he refers to the use of “pointers to pointers” as a means to simplify list manipulation. I had done a lot of list manipulation, but I can’t recall ever using pointers to pointers to do it. So this struck me as something worth investigating further.

His explanation is as quick and efficient as the code he writes:

The use of pointers to pointers is typical of many list manipulation algorithms. It uses one succinct mechanism to deal with two conditions: the initial node in a possibly empty list, and the interior nodes of a nonempty list.

It may be hard to wrap your head around exactly what that means until you see a code example from the book that puts it to use. The function below is the first of many examples that does so. It appends one linked list to the end of another, and returns the result. It seemed prudent to also include the list structure definitions, but the code to focus on is in the list_append function.

typedef struct List_T *List_T;

struct List_T {

List_T next;

void *item;

}; List_T list_append(List_T list, List_T tail) {

List_T *p = &list; while(*p)

p = &(*p)->next; *p = tail; return list;

}

Don’t worry if you don’t immediately understand this function. I didn’t at first either. Luckily I had the book to help me. Here is the explanation of this function that the author provides:

list_append walks p down list until it points to a null pointer at the end of the list to which tail should be assigned. If list itself is the null pointer, p ends up pointing to list, which has the desired effect of appending tail to the empty list.

I’m not sure how much that helps. In simpler terms, he is saying that by using a pointer to a pointer he has eliminated the need to check if list is empty (NULL), which would otherwise require an extra conditional statement to explicitly check for this case.

Maybe it’s just me, but in order to fully wrap my head around this concept I needed to write the same function without using a pointer to a pointer and compared the differences.

This is what I came up with:

typedef struct List_T *List_T;

struct List_T {

List_T next;

void *item;

}; List_T list_append(List_T list, List_T tail) {

List_T p = list;



if (p == NULL)

return tail;



while (p->next)

p = p->next; p->next = tail; return list;

}

I’ve tested the above code and it works exactly like the book’s example. The difference isn’t much. As presumed, I needed to add a special conditional statement to test if list is empty. There was no way that I could find to eliminate it without it returning an incorrect result, unless I used a pointer to a pointer.