@@ -1649,6 +1649,7 @@ unwrapped == 1234{#endsyntax#}</pre>
16491649 <li>{#link|Floats#}</li>
16501650 <li>{#link|bool|Primitive Types#}</li>
16511651 <li>{#link|type|Primitive Types#}</li>
1652+ <li>{#link|packed struct#}</li>
16521653 </ul>
16531654 </td>
16541655 <td>
@@ -2224,31 +2225,36 @@ or
22242225
22252226 {#header_open|packed struct#}
22262227 <p>
2227- Unlike normal structs, {#syntax#}packed{#endsyntax#} structs have guaranteed in-memory layout:
2228+ {#syntax#}packed{#endsyntax#} structs, like {#syntax#}enum{#endsyntax#}, are based on the concept
2229+ of interpreting integers differently. All packed structs have a <strong>backing integer</strong>,
2230+ which is implicitly determined by the total bit count of fields, or explicitly specified.
2231+ Packed structs have well-defined memory layout - exactly the same ABI as their backing integer.
2232+ </p>
2233+ <p>
2234+ Each field of a packed struct is interpreted as a logical sequence of bits, arranged from
2235+ least to most significant. Allowed field types:
22282236 </p>
22292237 <ul>
2230- <li>Fields remain in the order declared, least to most significant.</li>
2231- <li>There is no padding between fields.</li>
2232- <li>Zig supports arbitrary width {#link|Integers#} and although normally, integers with fewer
2233- than 8 bits will still use 1 byte of memory, in packed structs, they use
2234- exactly their bit width.
2235- </li>
2236- <li>{#syntax#}bool{#endsyntax#} fields use exactly 1 bit.</li>
2238+ <li>An {#link|integer|Integers#} field uses exactly as many bits as its
2239+ bit width. For example, a {#syntax#}u5{#endsyntax#} will use 5 bits of
2240+ the backing integer.</li>
2241+ <li>A {#link|bool|Primitive Types#} field uses exactly 1 bit.</li>
22372242 <li>An {#link|enum#} field uses exactly the bit width of its integer tag type.</li>
22382243 <li>A {#link|packed union#} field uses exactly the bit width of the union field with
22392244 the largest bit width.</li>
2240- <li>Packed structs support equality operators .</li>
2245+ <li>A {#syntax#}packed struct{#endsyntax#} field uses the bits of its backing integer .</li>
22412246 </ul>
22422247 <p>
22432248 This means that a {#syntax#}packed struct{#endsyntax#} can participate
22442249 in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory.
22452250 This even works at {#link|comptime#}:
22462251 </p>
22472252 {#code|test_packed_structs.zig#}
2248-
22492253 <p>
2250- The backing integer is inferred from the fields' total bit width.
2251- Optionally, it can be explicitly provided and enforced at compile time:
2254+ The backing integer can be inferred or explicitly provided. When
2255+ inferred, it will be unsigned. When explicitly provided, its bit width
2256+ will be enforced at compile time to exactly match the total bit width of
2257+ the fields:
22522258 </p>
22532259 {#code|test_missized_packed_struct.zig#}
22542260
@@ -2290,18 +2296,18 @@ or
22902296
22912297 <p>
22922298 Equating packed structs results in a comparison of the backing integer,
2293- and only works for the `==` and `!=` operators .
2299+ and only works for the {#syntax#}=={#endsyntax#} and {#syntax#}!={#endsyntax#} {#link|Operators#} .
22942300 </p>
22952301 {#code|test_packed_struct_equality.zig#}
22962302
22972303 <p>
2298- Using packed structs with {#link|volatile#} is problematic, and may be a compile error in the future.
2299- For details on this subscribe to
2300- <a href="https://github.com/ziglang/zig/issues/1761">this issue</a>.
2301- TODO update these docs with a recommendation on how to use packed structs with MMIO
2302- (the use case for volatile packed structs) once this issue is resolved.
2303- Don't worry, there will be a good solution for this use case in zig.
2304+ Field access and assignment can be understood as shorthand for bitshifts
2305+ on the backing integer. These operations are not {#link|atomic|Atomics#},
2306+ so beware using field access syntax when combined with memory-mapped
2307+ input-output (MMIO). Instead of field access on {#link|volatile#} {#link|Pointers#},
2308+ construct a fully-formed new value first, then write that value to the volatile pointer.
23042309 </p>
2310+ {#code|packed_struct_mmio.zig#}
23052311 {#header_close#}
23062312
23072313 {#header_open|Struct Naming#}
0 commit comments