If you, like me, are a C programmer you might have been asked on one of your job interviews a question like:
What is the difference between those four pointers?
uint8_t * p1;
const uint8_t * p2;
uint8_t * const p3;
const uint8_t * const p4;
And then you would respond with something like:
The first one is a pointer to uint8_t. One can modify the pointer value itself as well as the uint8_t value it points to.
The second one is a pointer to const uint8_t. One can modify only the pointer value itself. One cannot modify the value of the uint8_t it points to (as it is const uint8_t).
The third one is a const pointer to uint8_t. One cannot modify the pointer value itself (as it is a const pointer). Only the value of the uint8_t the pointer points to can be modified.
The fourth one is a const pointer to a const uint8_t. One cannot modify neither the pointer value itself nor the value of the const uint8_t it points to.
That is a lot of words. Let us look at the code for better understanding (using the pointers defined previously):
// we assume pointers are 32-bits long
p1 = (uint8_t *)0x11115555; // OK
*p1 = 3; // OK
p2 = (uint8_t *)0x11115555; // OK
*p2 = 3; // not OK, pointer points to a const value
p3 = (uint8_t *)0x11115555; // not OK, pointer is const
*p3 = 3; // OK
p4 = (uint8_t *)0x11115555; // not OK, pointer is const
*p4 = 3; // not OK, pointer points to a const value
At this point it should be clear to everyone what we call different type of pointer in the C world. What is a const pointer, what is a pointer to const and what is the difference between them.
When I was starting exploring Zig, I was reading some articles (like When a var really isn't a var by @gowind), watching some videos (like Solving Common Pointer Conundrums by @kristoff) and looking at the documentation.
And I could not understand how pointers and const work together in Zig. But one day I finally got it. Moreover, I got also why it was so confusing. Maybe, it was a source of @gowind's confusion when he was writing his article. Maybe, it was/is/will be a source of confusion for other C developers.
It turned out that Zig have exactly the same four variations of pointer as C:
var p1: *u8 = undefined; // C pointer to u8 , uint8_t * p1
var p2: *const u8 = undefined; // C pointer to const u8 , const uint8_t * p2
const p3: *u8 = undefined; // C const pointer to u8 , uint8_t * const p3
const p4: *const u8 = undefined; // C const pointer to const u8, const uint8_t * const p4
There is one caveat, though. What a C developer calls pointer to const in Zig is called const pointer. One example of such terminology can be found in official documentation (see test_single_item_pointer.zig in Pointers section, where pointer to a const is described as const single-item pointer). "Const pointer" was also used several times by @kristoff in his youtube talk.
In my humble opinion using such a convention is a significant mistake for two main reasons:
- It is utterly confusing to people who have some C background.
- It makes is it more difficult to explain properly the whole concept (even @kristoff struggled a lot in his talk and I am not convinced how many people got it).
Additionally, it could make other concepts unclear (e.g. one could ask why it is possible to modify the value that a pointer points to, when this pointer is a function argument, therefore it should be a const pointer and Zig const pointers do not allow to modify the value they point to).
Zig provides lovely compatibility with C on many different levels. Maybe it is not a bad idea to use C-compatible terminology too?