| ... | @@ -1651,7 +1651,7 @@ fn foo(bytes: []u8) u32 { | ... | @@ -1651,7 +1651,7 @@ fn foo(bytes: []u8) u32 { |
| 1651 | <pre><code class="zig">@ptrCast(*u32, f32(12.34)).*</code></pre> | 1651 | <pre><code class="zig">@ptrCast(*u32, f32(12.34)).*</code></pre> |
| 1652 | <p>Instead, use {#link|@bitCast#}: | 1652 | <p>Instead, use {#link|@bitCast#}: |
| 1653 | <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre> | 1653 | <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre> |
| 1654 | <p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p> | 1654 | <p>As an added benefit, the <code>@bitCast</code> version works at compile-time.</p> |
| 1655 | {#see_also|Slices|Memory#} | 1655 | {#see_also|Slices|Memory#} |
| 1656 | {#header_close#} | 1656 | {#header_close#} |
| 1657 | {#header_close#} | 1657 | {#header_close#} |
| ... | @@ -3551,13 +3551,91 @@ const optional_value: ?i32 = null; | ... | @@ -3551,13 +3551,91 @@ const optional_value: ?i32 = null; |
| 3551 | <p>TODO: ptrcast builtin</p> | 3551 | <p>TODO: ptrcast builtin</p> |
| 3552 | <p>TODO: explain number literals vs concrete types</p> | 3552 | <p>TODO: explain number literals vs concrete types</p> |
| 3553 | {#header_close#} | 3553 | {#header_close#} |
| | 3554 | |
| 3554 | {#header_open|void#} | 3555 | {#header_open|void#} |
| 3555 | <p>TODO: assigning void has no codegen</p> | 3556 | <p> |
| 3556 | <p>TODO: hashmap with void becomes a set</p> | 3557 | <code>void</code> represents a type that has no value. Code that makes use of void values is |
| 3557 | <p>TODO: difference between c_void and void</p> | 3558 | not included in the final generated code: |
| 3558 | <p>TODO: void is the default return value of functions</p> | 3559 | </p> |
| 3559 | <p>TODO: functions require assigning the return value</p> | 3560 | {#code_begin|syntax#} |
| | 3561 | export fn entry() void { |
| | 3562 | var x: void = {}; |
| | 3563 | var y: void = {}; |
| | 3564 | x = y; |
| | 3565 | } |
| | 3566 | {#code_end#} |
| | 3567 | <p>When this turns into LLVM IR, there is no code generated in the body of <code>entry</code>, |
| | 3568 | even in debug mode. For example, on x86_64:</p> |
| | 3569 | <pre><code>0000000000000010 &lt;entry&gt;: |
| | 3570 | 10:	55 	push %rbp |
| | 3571 | 11:	48 89 e5 	mov %rsp,%rbp |
| | 3572 | 14:	5d 	pop %rbp |
| | 3573 | 15:	c3 	retq </code></pre> |
| | 3574 | <p>These assembly instructions do not have any code associated with the void values - |
| | 3575 | they only perform the function call prologue and epilog.</p> |
| | 3576 | <p> |
| | 3577 | <code>void</code> can be useful for instantiating generic types. For example, given a |
| | 3578 | <code>Map(Key, Value)</code>, one can pass <code>void</code> for the <code>Value</code> |
| | 3579 | type to make it into a <code>Set</code>: |
| | 3580 | </p> |
| | 3581 | {#code_begin|test#} |
| | 3582 | const std = @import("std"); |
| | 3583 | const assert = std.debug.assert; |
| | 3584 | |
| | 3585 | test "turn HashMap into a set with void" { |
| | 3586 | var map = std.HashMap(i32, void, hash_i32, eql_i32).init(std.debug.global_allocator); |
| | 3587 | defer map.deinit(); |
| | 3588 | |
| | 3589 | _ = try map.put(1, {}); |
| | 3590 | _ = try map.put(2, {}); |
| | 3591 | |
| | 3592 | assert(map.contains(2)); |
| | 3593 | assert(!map.contains(3)); |
| | 3594 | |
| | 3595 | _ = map.remove(2); |
| | 3596 | assert(!map.contains(2)); |
| | 3597 | } |
| | 3598 | |
| | 3599 | fn hash_i32(x: i32) u32 { |
| | 3600 | return @bitCast(u32, x); |
| | 3601 | } |
| | 3602 | |
| | 3603 | fn eql_i32(a: i32, b: i32) bool { |
| | 3604 | return a == b; |
| | 3605 | } |
| | 3606 | {#code_end#} |
| | 3607 | <p>Note that this is different than using a dummy value for the hash map value. |
| | 3608 | By using <code>void</code> as the type of the value, the hash map entry type has no value field, and |
| | 3609 | thus the hash map takes up less space. Further, all the code that deals with storing and loading the |
| | 3610 | value is deleted, as seen above. |
| | 3611 | </p> |
| | 3612 | <p> |
| | 3613 | <code>void</code> is distinct from <code>c_void</code>, which is defined like this: |
| | 3614 | <code>pub const c_void = @OpaqueType();</code>. |
| | 3615 | <code>void</code> has a known size of 0 bytes, and <code>c_void</code> has an unknown, but non-zero, size. |
| | 3616 | </p> |
| | 3617 | <p> |
| | 3618 | Expressions of type <code>void</code> are the only ones whose value can be ignored. For example: |
| | 3619 | </p> |
| | 3620 | {#code_begin|test_err|expression value is ignored#} |
| | 3621 | test "ignoring expression value" { |
| | 3622 | foo(); |
| | 3623 | } |
| | 3624 | |
| | 3625 | fn foo() i32 { |
| | 3626 | return 1234; |
| | 3627 | } |
| | 3628 | {#code_end#} |
| | 3629 | <p>However, if the expression has type <code>void</code>:</p> |
| | 3630 | {#code_begin|test#} |
| | 3631 | test "ignoring expression value" { |
| | 3632 | foo(); |
| | 3633 | } |
| | 3634 | |
| | 3635 | fn foo() void {} |
| | 3636 | {#code_end#} |
| 3560 | {#header_close#} | 3637 | {#header_close#} |
| | 3638 | |
| 3561 | {#header_open|this#} | 3639 | {#header_open|this#} |
| 3562 | <p>TODO: example of this referring to Self struct</p> | 3640 | <p>TODO: example of this referring to Self struct</p> |
| 3563 | <p>TODO: example of this referring to recursion function</p> | 3641 | <p>TODO: example of this referring to recursion function</p> |