| ... | @@ -1824,7 +1824,7 @@ fn foo(bytes: []u8) u32 { | ... | @@ -1824,7 +1824,7 @@ fn foo(bytes: []u8) u32 { |
| 1824 | } | 1824 | } |
| 1825 | {#code_end#} | 1825 | {#code_end#} |
| 1826 | {#header_close#} | 1826 | {#header_close#} |
| 1827 | {#see_also|C Pointers#} | 1827 | {#see_also|C Pointers|Pointers to Zero Bit Types#} |
| 1828 | {#header_close#} | 1828 | {#header_close#} |
| 1829 | | 1829 | |
| 1830 | {#header_open|Slices#} | 1830 | {#header_open|Slices#} |
| ... | @@ -4464,9 +4464,20 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { | ... | @@ -4464,9 +4464,20 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { |
| 4464 | {#header_close#} | 4464 | {#header_close#} |
| 4465 | {#header_close#} | 4465 | {#header_close#} |
| 4466 | | 4466 | |
| 4467 | {#header_open|void#} | 4467 | {#header_open|Zero Bit Types#} |
| | 4468 | <p>For some types, {#link|@sizeOf#} is 0:</p> |
| | 4469 | <ul> |
| | 4470 | <li>{#link|void#}</li> |
| | 4471 | <li>The {#link|Integers#} {#syntax#}u0{#endsyntax#} and {#syntax#}i0{#endsyntax#}.</li> |
| | 4472 | <li>{#link|Arrays#} and {#link|Vectors#} with len 0, or with an element type that is a zero bit type.</li> |
| | 4473 | <li>An {#link|enum#} with only 1 tag.</li> |
| | 4474 | <li>An {#link|struct#} with all fields being zero bit types.</li> |
| | 4475 | <li>A {#link|union#} with only 1 field which is a zero bit type.</li> |
| | 4476 | <li>{#link|Pointers to Zero Bit Types#} are themselves zero bit types.</li> |
| | 4477 | </ul> |
| 4468 | <p> | 4478 | <p> |
| 4469 | {#syntax#}void{#endsyntax#} represents a type that has no value. Code that makes use of void values is | 4479 | These types can only ever have one possible value, and thus |
| | 4480 | require 0 bits to represent. Code that makes use of these types is |
| 4470 | not included in the final generated code: | 4481 | not included in the final generated code: |
| 4471 | </p> | 4482 | </p> |
| 4472 | {#code_begin|syntax#} | 4483 | {#code_begin|syntax#} |
| ... | @@ -4476,8 +4487,8 @@ export fn entry() void { | ... | @@ -4476,8 +4487,8 @@ export fn entry() void { |
| 4476 | x = y; | 4487 | x = y; |
| 4477 | } | 4488 | } |
| 4478 | {#code_end#} | 4489 | {#code_end#} |
| 4479 | <p>When this turns into LLVM IR, there is no code generated in the body of {#syntax#}entry{#endsyntax#}, | 4490 | <p>When this turns into machine code, there is no code generated in the |
| 4480 | even in debug mode. For example, on x86_64:</p> | 4491 | body of {#syntax#}entry{#endsyntax#}, even in {#link|Debug#} mode. For example, on x86_64:</p> |
| 4481 | <pre><code>0000000000000010 &lt;entry&gt;: | 4492 | <pre><code>0000000000000010 &lt;entry&gt;: |
| 4482 | 10:	55 	push %rbp | 4493 | 10:	55 	push %rbp |
| 4483 | 11:	48 89 e5 	mov %rsp,%rbp | 4494 | 11:	48 89 e5 	mov %rsp,%rbp |
| ... | @@ -4485,6 +4496,8 @@ export fn entry() void { | ... | @@ -4485,6 +4496,8 @@ export fn entry() void { |
| 4485 | 15:	c3 	retq </code></pre> | 4496 | 15:	c3 	retq </code></pre> |
| 4486 | <p>These assembly instructions do not have any code associated with the void values - | 4497 | <p>These assembly instructions do not have any code associated with the void values - |
| 4487 | they only perform the function call prologue and epilog.</p> | 4498 | they only perform the function call prologue and epilog.</p> |
| | 4499 | |
| | 4500 | {#header_open|void#} |
| 4488 | <p> | 4501 | <p> |
| 4489 | {#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a | 4502 | {#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a |
| 4490 | {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#} | 4503 | {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#} |
| ... | @@ -4556,6 +4569,38 @@ fn foo() i32 { | ... | @@ -4556,6 +4569,38 @@ fn foo() i32 { |
| 4556 | {#code_end#} | 4569 | {#code_end#} |
| 4557 | {#header_close#} | 4570 | {#header_close#} |
| 4558 | | 4571 | |
| | 4572 | {#header_open|Pointers to Zero Bit Types#} |
| | 4573 | <p>Pointers to zero bit types also have zero bits. They always compare equal to each other:</p> |
| | 4574 | {#code_begin|test#} |
| | 4575 | const std = @import("std"); |
| | 4576 | const assert = std.debug.assert; |
| | 4577 | |
| | 4578 | test "pointer to empty struct" { |
| | 4579 | const Empty = struct {}; |
| | 4580 | var a = Empty{}; |
| | 4581 | var b = Empty{}; |
| | 4582 | var ptr_a = &a; |
| | 4583 | var ptr_b = &b; |
| | 4584 | comptime assert(ptr_a == ptr_b); |
| | 4585 | } |
| | 4586 | {#code_end#} |
| | 4587 | <p>The type being pointed to can only ever be one value; therefore loads and stores are |
| | 4588 | never generated. {#link|ptrToInt#} and {#link|intToPtr#} are not allowed:</p> |
| | 4589 | {#code_begin|test_err#} |
| | 4590 | const Empty = struct {}; |
| | 4591 | |
| | 4592 | test "@ptrToInt for pointer to zero bit type" { |
| | 4593 | var a = Empty{}; |
| | 4594 | _ = @ptrToInt(&a); |
| | 4595 | } |
| | 4596 | |
| | 4597 | test "@intToPtr for pointer to zero bit type" { |
| | 4598 | _ = @intToPtr(*Empty, 0x1); |
| | 4599 | } |
| | 4600 | {#code_end#} |
| | 4601 | {#header_close#} |
| | 4602 | {#header_close#} |
| | 4603 | |
| 4559 | {#header_open|comptime#} | 4604 | {#header_open|comptime#} |
| 4560 | <p> | 4605 | <p> |
| 4561 | Zig places importance on the concept of whether an expression is known at compile-time. | 4606 | Zig places importance on the concept of whether an expression is known at compile-time. |