Posted on

Pointers and constness in Zig (and why it is confusing to a C programmer)

C pointers

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Zig pointers

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 
Enter fullscreen mode Exit fullscreen mode

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:

  1. It is utterly confusing to people who have some C background.
  2. 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?

Top comments (6)

michaellehn profile image
Michael • Edited

I love the grammar that Zig uses for declarations. In C that is the worst part of the language. And it is the hardest part when you teach C.

The grammar used in Zig is similar to Pascal/Modula/Oberon. Very readable. But I also wonder why the naming is not as you would read it:

var p1: *u8 = undefined; // variable p1 is a pointer to a u8
var p2: *const u8 = undefined; // variable p2 is a pointer to constant u8
const p3: *u8 = undefined; // constant p3 is a pointer to a u8
const p4: *const u8 = undefined; // constant p4 is a pointer to a constant u8
Enter fullscreen mode Exit fullscreen mode
voilaneighbor profile image

That last code block is a neat mapping.

allanmac profile image
Allan MacKinnon

Nice post. Thanks for summarizing!

zaya6 profile image

Doesn’t seem to confusing to me, at least the zig types are vastly more readable

axlescalada profile image

Nice post! This is really helpful

jimying profile image

good job