Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc,langref: mention diffs of Zig and C packed structs #21413

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

pgy
Copy link

@pgy pgy commented Sep 14, 2024

I've been bitten by this nuance in the wild while using std.mem.sliceAsBytes on an array of packed structs and felt like it deserved a paragraph in the docs. Feel free to reject this PR without explanation if you disagree -- I'm not very familiar with the Zig project.

Closest issue I could find was #12960

@rohlem
Copy link
Contributor

rohlem commented Sep 15, 2024

I agree this is a gotcha; two little nitpicks:

  • Instead of "the storage size of the struct in memory" I'd write "the storage size of the struct in a non-packed memory location".
    Specifically as a field of another packed struct, it does exactly bound the size as one would expect.
    (If this sounds too alien, I guess we could also add ", unless as a field of another packed struct.
  • The proposed wording if the backing integer is not a power of two is an unnecessary oversimplification in my eyes.
    From what I understand, the compiler is always able to pad and over-align any type it desires, unless specifically requested/guaranteed otherwise via the language.
    It might be better to mention directly (f.e. as inline comment in the example) that it's up to the compiler (+ compilation options, target etc.) what @sizeOf and @alignOf for any given type yield,
    so the correct solution is to always document any assumptions your code makes using comptime assertions (or tests).

@pgy
Copy link
Author

pgy commented Sep 15, 2024

I think the confusion arises because "packed" means something very different in the C world. In C, a packed struct means that the size of the struct "is the sum of the lengths of its fields", while in Zig (as far as I understand it) a packed struct is really syntax sugar for bit-packing into a backing integer or another packed struct.

For example CPacked in C has sizeof 13 and alignof 1, while ZigPacked in Zig has @sizeOf 16 and @alignOf 8 in an "unpacked context" and can be packed into 104 bits in a "packed context" (in which case there is no point in talking about byte size or byte alignment). These are very different things, so I think the best would be to mention this difference in the docs.

struct __attribute__((packed)) CPacked {
    double x;
    float y;
    char q;
};
const ZigPacked = packed struct {
    x: f64,
    y: f32,
    q: u8,
};

@pgy
Copy link
Author

pgy commented Sep 15, 2024

I changed the PR to document what I described in #21413 (comment)

@pgy pgy marked this pull request as draft September 15, 2024 11:33
@pgy pgy changed the title doc: mention size of packed struct(non-power-of-two-int) doc,langref: mention diffs of Zig and C packed structs Sep 15, 2024
@alexrp
Copy link
Contributor

alexrp commented Sep 17, 2024

Related: #12852

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants