| ... | @@ -1649,6 +1649,7 @@ unwrapped == 1234{#endsyntax#}</pre> | ... | @@ -1649,6 +1649,7 @@ unwrapped == 1234{#endsyntax#}</pre> |
| 1649 | <li>{#link|Floats#}</li> | 1649 | <li>{#link|Floats#}</li> |
| 1650 | <li>{#link|bool|Primitive Types#}</li> | 1650 | <li>{#link|bool|Primitive Types#}</li> |
| 1651 | <li>{#link|type|Primitive Types#}</li> | 1651 | <li>{#link|type|Primitive Types#}</li> |
| | 1652 | <li>{#link|packed struct#}</li> |
| 1652 | </ul> | 1653 | </ul> |
| 1653 | </td> | 1654 | </td> |
| 1654 | <td> | 1655 | <td> |
| ... | @@ -2224,20 +2225,24 @@ or | ... | @@ -2224,20 +2225,24 @@ or |
| 2224 | | 2225 | |
| 2225 | {#header_open|packed struct#} | 2226 | {#header_open|packed struct#} |
| 2226 | <p> | 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 | </p> | 2236 | </p> |
| 2229 | <ul> | 2237 | <ul> |
| 2230 | <li>Fields remain in the order declared, least to most significant.</li> | 2238 | <li>An {#link|integer|Integers#} field uses exactly as many bits as its |
| 2231 | <li>There is no padding between fields.</li> | 2239 | bit width. For example, a {#syntax#}u5{#endsyntax#} will use 5 bits of |
| 2232 | <li>Zig supports arbitrary width {#link|Integers#} and although normally, integers with fewer | 2240 | the backing integer.</li> |
| 2233 | than 8 bits will still use 1 byte of memory, in packed structs, they use | 2241 | <li>A {#link|bool|Primitive Types#} field uses exactly 1 bit.</li> |
| 2234 | exactly their bit width. | | |
| 2235 | </li> | | |
| 2236 | <li>{#syntax#}bool{#endsyntax#} fields use exactly 1 bit.</li> | | |
| 2237 | <li>An {#link|enum#} field uses exactly the bit width of its integer tag type.</li> | 2242 | <li>An {#link|enum#} field uses exactly the bit width of its integer tag type.</li> |
| 2238 | <li>A {#link|packed union#} field uses exactly the bit width of the union field with | 2243 | <li>A {#link|packed union#} field uses exactly the bit width of the union field with |
| 2239 | the largest bit width.</li> | 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 | </ul> | 2246 | </ul> |
| 2242 | <p> | 2247 | <p> |
| 2243 | This means that a {#syntax#}packed struct{#endsyntax#} can participate | 2248 | This means that a {#syntax#}packed struct{#endsyntax#} can participate |
| ... | @@ -2245,10 +2250,11 @@ or | ... | @@ -2245,10 +2250,11 @@ or |
| 2245 | This even works at {#link|comptime#}: | 2250 | This even works at {#link|comptime#}: |
| 2246 | </p> | 2251 | </p> |
| 2247 | {#code|test_packed_structs.zig#} | 2252 | {#code|test_packed_structs.zig#} |
| 2248 | | | |
| 2249 | <p> | 2253 | <p> |
| 2250 | The backing integer is inferred from the fields' total bit width. | 2254 | The backing integer can be inferred or explicitly provided. When |
| 2251 | Optionally, it can be explicitly provided and enforced at compile time: | 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 | </p> | 2258 | </p> |
| 2253 | {#code|test_missized_packed_struct.zig#} | 2259 | {#code|test_missized_packed_struct.zig#} |
| 2254 | | 2260 | |
| ... | @@ -2290,18 +2296,18 @@ or | ... | @@ -2290,18 +2296,18 @@ or |
| 2290 | | 2296 | |
| 2291 | <p> | 2297 | <p> |
| 2292 | Equating packed structs results in a comparison of the backing integer, | 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 | </p> | 2300 | </p> |
| 2295 | {#code|test_packed_struct_equality.zig#} | 2301 | {#code|test_packed_struct_equality.zig#} |
| 2296 | | 2302 | |
| 2297 | <p> | 2303 | <p> |
| 2298 | Using packed structs with {#link|volatile#} is problematic, and may be a compile error in the future. | 2304 | Field access and assignment can be understood as shorthand for bitshifts |
| 2299 | For details on this subscribe to | 2305 | on the backing integer. These operations are not {#link|atomic|Atomics#}, |
| 2300 | <a href="https://github.com/ziglang/zig/issues/1761">this issue</a>. | 2306 | so beware using field access syntax when combined with memory-mapped |
| 2301 | TODO update these docs with a recommendation on how to use packed structs with MMIO | 2307 | input-output (MMIO). Instead of field access on {#link|volatile#} {#link|Pointers#}, |
| 2302 | (the use case for volatile packed structs) once this issue is resolved. | 2308 | construct a fully-formed new value first, then write that value to the volatile pointer. |
| 2303 | Don't worry, there will be a good solution for this use case in zig. | | |
| 2304 | </p> | 2309 | </p> |
| | 2310 | {#code|packed_struct_mmio.zig#} |
| 2305 | {#header_close#} | 2311 | {#header_close#} |
| 2306 | | 2312 | |
| 2307 | {#header_open|Struct Naming#} | 2313 | {#header_open|Struct Naming#} |