If you, like me, assumed that const in C relates to constant than this post will shock you. const will (at best) mean read-only; And if we talk about const-pointers even that is not given. In fact, the situation is much weirder.

Let's talk about what const does not guarantee. It certainly does not guarantee that successive reads through a const-pointer will produce the same result. This is easy to see in the following example:

int i = 1;
const int *cptr = &i;
printf("%i\n", *cptr); // 1
i = 2;
printf("%i\n", *cptr); // 2


That is a fully conforming C program (if you wrap it in a main). The const marks the pointer as read-only, and that is all we do. The underlying data however, is free to change at will. In this case the reason for the change is easy to spot, but one can easily make up cases where the side-effects of function-calls are harder to see. With multi-threading the behaviour is even more difficult to predict.

void f(const int *cptr) {
// do something
}


Looking at the function signature of f, we take a read-only pointer and return no value. Such a function only has a reason to exists, if it has a side-effect. Interestingly, one of the most important functions in C has such a type signature: kfree (the linux-kernel equivalent of free(3)).

As explained in this e-mail thread kfree does not modify the data, the original pointer goes to. Thus the parameter is marked const. However, it could legally modify the data by using a non-const pointer from one of the kernels internal data-structures. That is totally valid according to the C standard. A const and a non-const pointer are bit-identical w.r.t. the running machine, only one cannot perform writes.

int *data = kmalloc(64);
kfree(data);


Even weirder: Assuming kfree did modify the data, the user would have no legal way of finding out. After the caller passed data to kfree not only is the data gone, but the pointer itself is poisened. The C standard mandates that data cannot be used for anything else, not even a comparison with NULL. The only legal operation on data is overwriting it with a new address.

Summarising, const gives very little run-time guarantees. However, one has to remember that programming languages are for humans and thus const can be effectively used to prevent errors like accidental writes. As such it is a useful tool and its usage is encouraged.