Search code examples
structunionzig

Multiple anonymus structs inside a union (like in C)


I found this solution in the C library called handmade math:

typedef union hmm_vec2 {
  struct { float X, Y; };
  struct { float U, V; };
  struct { float Left, Right; };
  struct { float Width, Height; };
  float Elements[2];
} hmm_vec2;

In C, this solution allows you to refer to the same memory with different names. Let's say you have a variable called my_vec2, you could say my_vec2.x, my_vec2.Height, my_vec2[0]

The use for this is that you don't have to define different types for the same data-structure but with different field names.

Could you do something similar in Zig? I tried a bit but couldn't make it work.

Here's something I tried but doesn't work. I don't understand why fields don't get pulled with usingnamespace.

const vec2 = union {
  usingnamespace struct { x: i32, y: i32 };
  usingnamespace struct { w: i32, h: i32 };
  elems: [2]i32,
};

Solution

  • Some of this can be replicated with packed union and packed structs, but Zig doesn't allow arrays in either packed union or packed struct.

    const log = @import("std").log;
    
    const TestUnion = packed union {
        coords: packed struct { x: f32, y: f32 },
        size: packed struct { width: f32, height: f32 },
        // elements: [2]f32, // error: packed unions cannot contain fields of type '[2]f32'
                             // note: type has no guaranteed in-memory representation
    };
    
    pub fn main() !void {
        const test_union = TestUnion{ .coords = .{ .x = 1.2, .y = 3.4 } };
    
        log.info("coords: {}, {}", .{ test_union.coords.x, test_union.coords.y });
        log.info("size: {}, {}", .{ test_union.size.width, test_union.size.height });
    }
    
    $ zig build run
    info: coords: 1.2e0, 3.4e0
    info: size: 1.2e0, 3.4e0