const *const pointers in function parameters

Viewed 69

I have a question about best practices involving pointers in function parameters and whether they should be specified as *const or const *const. I know there are varying opinions on use, or excessive use, of const, but at least some use is a good way to catch accidental mistakes.

Say you have the following function, which is part of the implementation of a queue based on a linked list:

void enqueue(struct queue *q, void *data)
{
    struct queue_node *item = malloc(sizeof(*item));
    item->data = data;

    [add node to linked list, specifics are not relevant here]
}

struct queue_node is defined as

struct queue_node {
        struct queue_node *next;
        void *data;
};

data is not meant to be modified in this function, so it seems like a good idea for data to be of type void *const so you can't accidentally do something like data = item->data instead of item->data = data.

The next level would be to define data as const void *const which means you also can't change what data points to. However, this leads to a warning about discarding the const qualifier from the pointer. And if I understand correctly, further use of such a pointer is considered undefined behavior. Using a cast (item->data = (void *)data) seems clunky.

What's the best approach here? Is const void *const unnecessarily over-protective? It feels like void *const is sufficient to catch most errors.

1 Answers

Since changes to function parameters aren't reflected in the calling function, there's little reason to make sure the parameters themselves are read-only. It is useful however to ensure that what a pointer parameter points to doesn't change. So if you don't want what data points to to be changed, you would change the function signature to:

void enqueue(struct queue *q, const void *data)

Note that this will work only if the data member of struct queue_node has type const void *. If it doesn't, then you don't want to use const on the data parameter.

Related