# Casting a pointer to a pointer of its parent struct

**URL:** <https://ziggit.dev/t/casting-a-pointer-to-a-pointer-of-its-parent-struct/8330>\
**Category:** Help\
**Tags:** compiler\
**Created:** [February 3, 2025, 6:19am UTC](https://ziggit.dev/t/casting-a-pointer-to-a-pointer-of-its-parent-struct/8330 "2025-02-03T06:19:55Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![masa](https://ziggit.dev/letter_avatar_proxy/v4/letter/m/b38774/32.png) [@masa](https://ziggit.dev/u/masa)\
**Post date:** [February 3, 2025, 6:19am UTC](https://ziggit.dev/t/casting-a-pointer-to-a-pointer-of-its-parent-struct/8330/1 "2025-02-03T06:19:55Z")

</div>

Hi,

I’m a C programmer who recently started to learn Zig. I defined a base struct `NodeBase` and its child struct `NodeInternal` as follow:

```zig
const std = @import("std");
const Allocator = std.mem.Allocator;

const NodeKind = enum {
    Internal,
    Leaf,
};

const NodeBase = struct {
    kind: NodeKind,

    pub fn init(kind: NodeKind) NodeBase {
        return .{
            .kind = kind,
        };
    }
};

const NodeLeaf = struct {
    base: NodeBase,
    child: *NodeBase,

    pub fn create(allocator: Allocator) !*NodeLeaf {
        var n = try allocator.create(NodeLeaf);
        n.base = NodeBase.init(NodeKind.Leaf);
        n.child = undefined;
        return n;
    }
};

```

And wanted to access a field (`kind`) of the base struct in the NodeInternal by casting a pointer type as follow:

```zig
pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const leaf_n = try NodeLeaf.create(allocator);
    const base_n: *NodeBase = @ptrCast(leaf_n);

    std.debug.print("align-of\t: leaf_n {d}, base_n {d}\n", .{ @alignOf(NodeLeaf), @alignOf(NodeBase) });
    std.debug.print("pointer\t\t: leaf_n {*}, base_n {*}\n", .{ leaf_n, base_n });
    std.debug.print("kind\t\t: leaf_n {any} base_n {any}\n", .{ leaf_n.base.kind, base_n.kind });
    std.debug.print("ptr of kind\t: leaf_n {*} base_n {*}\n", .{ &(leaf_n.base.kind), &(base_n.kind) });
}

```

However, I got the different addresses with/without a pointer casting; the last output shows different addresses for the same field:

```zig
align-of : leaf_n 8, base_n 1
pointer : leaf_n main.NodeLeaf@104818000, base_n main.NodeBase@104818000
kind : leaf_n main.NodeKind.Leaf base_n main.NodeKind.Internal
ptr of kind : leaf_n main.NodeKind@104818008 base_n main.NodeKind@104818000

```

How can I get the correct address of `kind` even after a pointer casting?

---

<div class="post-metadata">

**Author:** ![squeek502](https://ziggit.dev/user_avatar/ziggit.dev/squeek502/32/409_2.png) [@squeek502](https://ziggit.dev/u/squeek502)\
**Post date:** [February 3, 2025, 6:40am UTC](https://ziggit.dev/t/casting-a-pointer-to-a-pointer-of-its-parent-struct/8330/2 "2025-02-03T06:40:22Z")

</div>

[`struct` in Zig does not have a defined layout](https://ziglang.org/documentation/master/#struct), so it can rearrange fields however it wants. In your case, it’s putting the `child` field first:

```zig
std.debug.print("offset-of\t: base {d}, child {d}\n", .{ @offsetOf(NodeLeaf, "base"), @offsetOf(NodeLeaf, "child") });

```

outputs

```plaintext
offset-of : base 8, child 0

```

One thing you can do instead: to get a `*NodeBase` pointer, get a pointer to the `base` field; you can then use [`@fieldParentPtr`](https://ziglang.org/documentation/master/#fieldParentPtr) to go from that pointer-to-a-field to a pointer to its “parent” struct ([further explanation from when I was first learning how this works](https://www.ryanliptak.com/blog/zig-fieldparentptr-for-dumbos/)).

Here’s your main function modified to show you what I mean:

```zig
pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const leaf_n = try NodeLeaf.create(allocator);
    const base_n: *NodeBase = &leaf_n.base;

    std.debug.print("align-of\t: leaf_n {d}, base_n {d}\n", .{ @alignOf(NodeLeaf), @alignOf(NodeBase) });
    std.debug.print("offset-of\t: base {d}, child {d}\n", .{ @offsetOf(NodeLeaf, "base"), @offsetOf(NodeLeaf, "child") });
    std.debug.print("pointer\t\t: leaf_n {*}, base_n {*}\n", .{ leaf_n, base_n });
    std.debug.print("kind\t\t: leaf_n {any} base_n {any}\n", .{ leaf_n.base.kind, base_n.kind });
    std.debug.print("ptr of kind\t: leaf_n {*} base_n {*}\n", .{ &(leaf_n.base.kind), &(base_n.kind) });

    const leaf_again: *NodeLeaf = @alignCast(@fieldParentPtr("base", base_n));
    std.debug.print("pointer\t\t: leaf_again {*}\n", .{leaf_again});
}

```

That outputs for me:

```plaintext
align-of : leaf_n 8, base_n 1
offset-of : base 8, child 0
pointer : leaf_n node-cast.NodeLeaf@18f780d0000, base_n node-cast.NodeBase@18f780d0008
kind : leaf_n node-cast.NodeKind.Leaf base_n node-cast.NodeKind.Leaf
ptr of kind : leaf_n node-cast.NodeKind@18f780d0008 base_n node-cast.NodeKind@18f780d0008
pointer : leaf_again node-cast.NodeLeaf@18f780d0000

```

Real world example:

- [AST `Node.Literal` definition](https://github.com/squeek502/resinator/blob/699becd5d535c2da20745306ce0c2a45aaedc714/src/ast.zig#L205-L208)
- [`*Node.Literal` creation and return](https://github.com/squeek502/resinator/blob/699becd5d535c2da20745306ce0c2a45aaedc714/src/parse.zig#L1055-L1059)
- [Going from `*Node` to `*Node.Literal`](https://github.com/squeek502/resinator/blob/699becd5d535c2da20745306ce0c2a45aaedc714/src/compile.zig#L1455-L1456)

* * *

If, instead, you want a guaranteed `struct` layout, you can use [`extern struct`](https://ziglang.org/documentation/master/#extern-struct) or [`packed struct`](https://ziglang.org/documentation/master/#packed-struct).

---

<div class="post-metadata">

**Author:** ![vulpesx](https://ziggit.dev/user_avatar/ziggit.dev/vulpesx/32/3989_2.png) [@vulpesx](https://ziggit.dev/u/vulpesx)\
**Post date:** [February 3, 2025, 6:52am UTC](https://ziggit.dev/t/casting-a-pointer-to-a-pointer-of-its-parent-struct/8330/3 "2025-02-03T06:52:23Z")

</div>

Your example isn’t trying to get a parent pointer but a field pointer, which you can do with just `&leaf_n.base`

---

<div class="post-metadata">

**Author:** ![squeek502](https://ziggit.dev/user_avatar/ziggit.dev/squeek502/32/409_2.png) [@squeek502](https://ziggit.dev/u/squeek502)\
**Post date:** [February 3, 2025, 6:55am UTC](https://ziggit.dev/t/casting-a-pointer-to-a-pointer-of-its-parent-struct/8330/4 "2025-02-03T06:55:05Z")

</div>

> [@masa](#):
>
> ```zig
> n.child = undefined;
> 
> ```

Also, just as an aside: double check that `undefined` is what you want to use here. [`undefined`](https://ziglang.org/documentation/master/#undefined) in Zig is a sharp tool that tells the compiler _this value will be changed before I do anything with it_. Comparing something against `undefined` is ([currently unchecked, but will be checked in the future](https://github.com/ziglang/zig/issues/211)) illegal behavior.

If there is any possibility of you using `child` before setting it to a real value, then you probably want an [optional](https://ziglang.org/documentation/master/#Optionals) instead:

```zig
    // note that an optional pointer is the same size as non-optional
    child: ?*NodeBase,

// ...

        n.child = null;

```
