# Zig Zaggin'

By Thorsten Ball • November 3, 2023

---

Here’s a very interesting bit of Zig that I came across again this week: `@fieldParentPtr`. It’s a prism through which you can see a lot of Zig’s character. That’s not what the official [docs](https://ziglang.org/documentation/master/#fieldParentPtr) say, of course. They say that `@fieldParentPtr`:

> Given a pointer to a field, returns the base pointer of a struct.

That doesn’t paint a, uhm, full picture, I’d say. So here’s some code:

```
const Parent = struct {
    name: []const u8,

    left: Child,
    right: Child,
};

const Child = struct {
    name: []const u8,

    position: enum {
        left,
        right,
    },

    fn parentName(self: *Child) []const u8 {
        const parent = switch (self.position) {
            .left => @fieldParentPtr(Parent, "left", self),
            .right => @fieldParentPtr(Parent, "right", self),
        };

        return parent.name;
    }
};
```

`Parent` has two `Child`ren, all three have a name and the `parentName` method on `Child` returns its parent’s name.

The interesting bit is the invocation of `@fieldParentPtr`:

```
@fieldParentPtr(Parent, "left", self)
```

What that says is: give me a pointer to `Parent`, based on the pointer of the `"left"` field on `Parent` that I’m giving you.

It’s doing pointer math for you!

What it does is take `self`, which is a pointer to a `Child`, look up the position of `left` field in `Parent`, then calculate how many bytes to subtract from `left` to get to the start of `Parent`, do that calculation and return a pointer to `Parent`.

Here’s roughly-equivalent C code to show what’s going on under the hood:

```
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>

enum position {
    LEFT,
    RIGHT
};

struct child {
    const char *name;
    enum position position;
};

struct parent {
    const char *name;
    struct child left;
    struct child right;
};

const char *parentName(const struct child *child) {
    uintptr_t offset = 0;
    switch (child->position) {
        // 1. Turn a `0` into a `struct parent *` pointer
        // 2. Access `->left` or `->right`, take pointer of that.
        // 3. That increased the `0` address to the field address
        // -> our offset
        case LEFT:
            offset = (uintptr_t) &(((struct parent *)0)->left);
            break;
        case RIGHT:
            offset = (uintptr_t) &(((struct parent *)0)->right);
            break;
    }
    // Now we can take that offset and get to the name
    struct parent *parent = (struct parent *)((char *)child - offset);
    return parent->name;
}

int main(void) {
    struct parent parent = {
        .name = "bob",
        .left = { .name = "child1", .position = LEFT },
        .right = { .name = "child2", .position = RIGHT },
    };

    assert(strcmp(parentName(&parent.left), "bob") == 0);
    assert(strcmp(parentName(&parent.right), "bob") == 0);

    printf("And bob's... not your uncle?\n");

    return 0;
}
```

What `@fieldParentPtr` does is what `parentName` does here, except it’s *compile-time safe!*

If I change the Zig code from

```
@fieldParentPtr(Parent, "left", self)
```

to

```
@fieldParentPtr(Parent, "in emergency: break dance", self)
```

it breaks!

```
field_parent_ptr_simple.zig:18:46: error: no field named 'in emergency: break dance' in struct 'f
ield_parent_ptr_simple.Parent'
            .left => @fieldParentPtr(Parent, "in emergency: break dance", self),
                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
```

One could [re-implement](https://www.ryanliptak.com/blog/zig-fieldparentptr-for-dumbos/)`@fieldParentPtr` in Zig without it being a compiler builtin. The fact it *is* a compiler builtin and that people use it to implement [interfaces in Zig](https://zig.news/david_vanderson/interfaces-in-zig-o1c) shows you what Zig is about.

It’s fun to learn.