@@ -1649,6 +1649,7 @@ unwrapped == 1234{#endsyntax#}</pre>
1649
1649
<li>{#link|Floats#}</li>
1650
1650
<li>{#link|bool|Primitive Types#}</li>
1651
1651
<li>{#link|type|Primitive Types#}</li>
1652
+ <li>{#link|packed struct#}</li>
1652
1653
</ul>
1653
1654
</td>
1654
1655
<td>
@@ -2224,31 +2225,36 @@ or
2224
2225
2225
2226
{#header_open|packed struct#}
2226
2227
<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:
2228
2236
</p>
2229
2237
<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>
2237
2242
<li>An {#link|enum#} field uses exactly the bit width of its integer tag type.</li>
2238
2243
<li>A {#link|packed union#} field uses exactly the bit width of the union field with
2239
2244
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>
2241
2246
</ul>
2242
2247
<p>
2243
2248
This means that a {#syntax#}packed struct{#endsyntax#} can participate
2244
2249
in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory.
2245
2250
This even works at {#link|comptime#}:
2246
2251
</p>
2247
2252
{#code|test_packed_structs.zig#}
2248
-
2249
2253
<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:
2252
2258
</p>
2253
2259
{#code|test_missized_packed_struct.zig#}
2254
2260
@@ -2290,18 +2296,18 @@ or
2290
2296
2291
2297
<p>
2292
2298
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#} .
2294
2300
</p>
2295
2301
{#code|test_packed_struct_equality.zig#}
2296
2302
2297
2303
<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.
2304
2309
</p>
2310
+ {#code|packed_struct_mmio.zig#}
2305
2311
{#header_close#}
2306
2312
2307
2313
{#header_open|Struct Naming#}
0 commit comments