How to find out a type's size without printing it manually?

It is very annoying for me to align struct fields in Zig. In the screenshot below, the popup on top shows the size of fd and its offset in a struct in Clion for the C language. The popup at the bottom shows the same type in a struct using the ZigBrains plugin for Clion.

Is there a code editor that supports this feature for Zig, or a program that does something similar? I am aware that I can print the size each struct and its fields to the console manually, but that is tedious and Clion has spoiled me with this feature in C.

not sure if zigbrains uses zls or not, gonna assume it does.
zls has an issue for it, but it’s not a priority

Could you be more specific about what you’re doing? Note that Zig’s struct doesn’t guarantee field order or struct size.

If you’re interoperating with C, then extern struct is probably what you want.

If you want a struct with all the fields tightly packed, then packed struct would work.

However, if you do want a specific alignment for a specific field in a regular struct, then you can use align(N) on a field like so (this is test_aligned_struct_fields.zig in the language reference):

const std = @import("std");
const expectEqual = std.testing.expectEqual;

test "aligned struct fields" {
    const S = struct {
        a: u32 align(2),
        b: u32 align(64),
    };
    var foo = S{ .a = 1, .b = 2 };

    try expectEqual(64, @alignOf(S));
    try expectEqual(*align(2) u32, @TypeOf(&foo.a));
    try expectEqual(*align(64) u32, @TypeOf(&foo.b));
}
6 Likes

By aligning struct fields I meant finding out a struct field’s size and padding without printing it out manually, like this in C.

Right, I’m asking why you want to know that information.

Here’s a more concrete example to illustrate what I mean:

const A = struct {
    c: u16,
    a: bool,
    b: bool,
};
comptime {
    @compileLog("A", @sizeOf(A), @bitOffsetOf(A, "a"), @bitOffsetOf(A, "b"), @bitOffsetOf(A, "c"));
}

const B = struct {
    a: bool,
    c: u16,
    b: bool,
};
comptime {
    @compileLog("B", @sizeOf(B), @bitOffsetOf(B, "a"), @bitOffsetOf(B, "b"), @bitOffsetOf(B, "c"));
}

const C = struct {
    a: bool,
    b: bool,
    c: u16,
};
comptime {
    @compileLog("C", @sizeOf(C), @bitOffsetOf(C, "a"), @bitOffsetOf(C, "b"), @bitOffsetOf(C, "c"));
}

When compiled, the compile logs will (currently) print:

@as(*const [1:0]u8, "A"), @as(comptime_int, 4), @as(comptime_int, 16), @as(comptime_int, 24), @as(comptime_int, 0)
@as(*const [1:0]u8, "B"), @as(comptime_int, 4), @as(comptime_int, 16), @as(comptime_int, 24), @as(comptime_int, 0)
@as(*const [1:0]u8, "C"), @as(comptime_int, 4), @as(comptime_int, 16), @as(comptime_int, 24), @as(comptime_int, 0)

That is, all 3 structs will have exactly the same layout (size of 4 bytes, fields ordered u16, bool, bool), even though the fields are all ordered differently in the definitions. And the Zig compiler is free to change that ordering/size at any point. If you notice it doing something suboptimal, the way to go would be to file an issue so that it gets fixed in the compiler.

In other words, for a regular struct in Zig, finding out what a struct’s size and padding are doesn’t really give you any actionable information. You’re only finding out what the compiler happens to be doing now, but that could always change. So, if you write any code that depends on a particular layout (like interoperating with C, or pointer casting between different structs, etc), then you are by definition writing buggy code when using a regular struct, and you should instead be reaching for extern struct (which guarantees a layout according to the C ABI) or packed struct (where the size/padding is easy to discern).

All that said, tooling to provide size/alignment/padding/etc information without needing to use @compileLog/etc would still be nice to have; this is just a caveat worth knowing.

3 Likes

I should have said I was using extern struct from the very beginning, sorry bout that. I want align struct fields to fit them in cache lines for a micro-controller. I do agree that a tool like this would be nice to have though.

2 Likes