| ... | @@ -3192,7 +3192,16 @@ fn foo() void { } | ... | @@ -3192,7 +3192,16 @@ fn foo() void { } |
| 3192 | {#code_end#} | 3192 | {#code_end#} |
| 3193 | {#header_open|Pass-by-value Parameters#} | 3193 | {#header_open|Pass-by-value Parameters#} |
| 3194 | <p> | 3194 | <p> |
| 3195 | In Zig, structs, unions, and enums with payloads can be passed directly to a function: | 3195 | Primitive types such as {#link|Integers#} and {#link|Floats#} passed as parameters |
| | 3196 | are copied, and then the copy is available in the function body. This is called "passing by value". |
| | 3197 | Copying a primitive type is essentially free and typically involves nothing more than |
| | 3198 | setting a register. |
| | 3199 | </p> |
| | 3200 | <p> |
| | 3201 | Structs, unions, and arrays can sometimes be more efficiently passed as a reference, since a copy |
| | 3202 | could be arbitrarily expensive depending on the size. When these types are passed |
| | 3203 | as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way |
| | 3204 | Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable. |
| 3196 | </p> | 3205 | </p> |
| 3197 | {#code_begin|test#} | 3206 | {#code_begin|test#} |
| 3198 | const Point = struct { | 3207 | const Point = struct { |
| ... | @@ -3201,20 +3210,20 @@ const Point = struct { | ... | @@ -3201,20 +3210,20 @@ const Point = struct { |
| 3201 | }; | 3210 | }; |
| 3202 | | 3211 | |
| 3203 | fn foo(point: Point) i32 { | 3212 | fn foo(point: Point) i32 { |
| | 3213 | // Here, `point` could be a reference, or a copy. The function body |
| | 3214 | // can ignore the difference and treat it as a value. Be very careful |
| | 3215 | // taking the address of the parameter - it should be treated as if |
| | 3216 | // the address will become invalid when the function returns. |
| 3204 | return point.x + point.y; | 3217 | return point.x + point.y; |
| 3205 | } | 3218 | } |
| 3206 | | 3219 | |
| 3207 | const assert = @import("std").debug.assert; | 3220 | const assert = @import("std").debug.assert; |
| 3208 | | 3221 | |
| 3209 | test "pass aggregate type by non-copy value to function" { | 3222 | test "pass struct to function" { |
| 3210 | assert(foo(Point{ .x = 1, .y = 2 }) == 3); | 3223 | assert(foo(Point{ .x = 1, .y = 2 }) == 3); |
| 3211 | } | 3224 | } |
| 3212 | {#code_end#} | 3225 | {#code_end#} |
| 3213 | <p> | 3226 | <p> |
| 3214 | In this case, the value may be passed by reference, or by value, whichever way | | |
| 3215 | Zig decides will be faster. | | |
| 3216 | </p> | | |
| 3217 | <p> | | |
| 3218 | For extern functions, Zig follows the C ABI for passing structs and unions by value. | 3227 | For extern functions, Zig follows the C ABI for passing structs and unions by value. |
| 3219 | </p> | 3228 | </p> |
| 3220 | {#header_close#} | 3229 | {#header_close#} |