Contents
- {#nav#} + a { + color: #88f; + } + a:hover,a:focus { + color: #000; + } + table, th, td { + border-color: grey; + } + .t2_0 { + color: grey; + } + .t31_1 { + color: red; + } + .t32_1 { + color: #00B800; + } + .t36_1 { + color: #0086b3; + } + code { + background: #222; + border-color: #444; + } + pre > code { + color: #ccc; + background: #222; + border: unset; + } + samp { + background: #000; + color: #ccc; + } + pre > samp { + border: unset; + } + .tok-kw { + color: #eee; + } + .tok-str { + color: #2e5; + } + .tok-builtin { + color: #ff894c; + } + .tok-comment { + color: #aa7; + } + .tok-fn { + color: #B1A0F8; + } + .tok-null { + color: #ff8080; + } + .tok-number { + color: #ff8080; + } + .tok-type { + color: #68f; + } + h1 a, h2 a, h3 a, h4 a, h5 a { + color: #aaa; + } + figcaption.zig-cap { + background-color: #b27306; + color: #000; + } + figcaption.shell-cap { + background: #2a2a2a; + color: #fff; + } + } + + + +Zig Language Reference
- Zig is a general-purpose programming language and toolchain for maintaining + Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
--
-
- Robust - behavior is correct even for edge cases such as out of memory. -
- Optimal - write programs the best way they can behave and perform. -
- Reusable - the same code works in many environments which have different - constraints. -
- Maintainable - precisely communicate intent to the compiler and
+
-
+
- Robust
- Behavior is correct even for edge cases such as out of memory. +
- Optimal
- Write programs the best way they can behave and perform. +
- Reusable
- The same code works in many environments which have different + constraints. +
- Maintainable
- Precisely communicate intent to the compiler and other programmers. The language imposes a low overhead to reading code and is - resilient to changing requirements and environments.
-
Often the most efficient way to learn something new is to see examples, so this documentation shows how to use each of Zig's features. It is @@ -236,8 +323,16 @@
This HTML document depends on no external files, so you can use it offline.
+ {#header_close#} + + {#header_open|Zig Standard Library#}- Where is the documentation for the Zig standard library? + The Zig Standard Library has its own documentation. +
++ Zig's Standard Library contains commonly used algorithms, data structures, and definitions to help you build programs or libraries. + You will see many examples of Zig's Standard Library used in this documentation. To learn more about the Zig Standard Library, + visit the link above.
{#header_close#} @@ -252,96 +347,102 @@ pub fn main() !void { } {#code_end#}
- The Zig code sample above demonstrates one way to create a program that will output Hello, world!.
+ The Zig code sample above demonstrates one way to create a program that will output: Hello, world!.
- The code sample shows the contents of a file named hello.zig. Files storing Zig
+ The code sample shows the contents of a file named hello.zig. Files storing Zig
source code are {#link|UTF-8 encoded|Source Encoding#} text files. The files storing
- Zig source code are usually named with the .zig extension.
+ Zig source code are usually named with the .zig extension.
- Following the hello.zig Zig code sample, the {#link|Zig Build System#} is used
- to build an executable program from the hello.zig source code. Then, the
- hello program is executed showing its output Hello, world!. The
- lines beginning with $ represent command line prompts and a command.
+ Following the hello.zig Zig code sample, the {#link|Zig Build System#} is used
+ to build an executable program from the hello.zig source code. Then, the
+ hello program is executed showing its output Hello, world!. The
+ lines beginning with $ represent command line prompts and a command.
Everything else is program output.
- The code sample begins by adding Zig's Standard Library to the build using the {#link|@import#} builtin function.
- The {#syntax#}@import("std"){#endsyntax#} function call creates a structure to represent the Standard Library.
+ The code sample begins by adding the {#link|Zig Standard Library#} to the build using the {#link|@import#} builtin function.
+ The {#syntax#}@import("std"){#endsyntax#} function call creates a structure that represents the Zig Standard Library.
The code then {#link|declares|Container Level Variables#} a
- {#link|constant identifier|Assignment#}, named std, for easy access to
- Zig's standard library.
+ {#link|constant identifier|Assignment#}, named {#syntax#}std{#endsyntax#}, that gives access the features of the Zig Standard Library.
- Next, a {#link|public function|Functions#}, {#syntax#}pub fn{#endsyntax#}, named main
- is declared. The main function is necessary because it tells the Zig compiler where the start of
+ Next, a {#link|public function|Functions#}, {#syntax#}pub fn{#endsyntax#}, named {#syntax#}main{#endsyntax#}
+ is declared. The {#syntax#}main{#endsyntax#} function is necessary because it tells the Zig compiler where the start of
the program exists. Programs designed to be executed will need a {#syntax#}pub fn main{#endsyntax#} function.
- For more advanced use cases, Zig offers other features to inform the compiler where the start of
- the program exists. Libraries, on the other hand, do not need a main function because
- library code is usually called by other programs.
A function is a block of any number of statements and expressions that, as a whole, perform a task. Functions may or may not return data after they are done performing their task. If a function cannot perform its task, it might return an error. Zig makes all of this explicit.
- In the hello.zig code sample, the main function is declared
+ In the hello.zig code sample, the main function is declared
with the {#syntax#}!void{#endsyntax#} return type. This return type is known as an {#link|Error Union Type#}.
This syntax tells the Zig compiler that the function will either return an
- error or a value. An error union type combines an {#link|Error Set Type#} and a {#link|Primitive Type|Primitive Types#}.
+ error or a value. An error union type combines an {#link|Error Set Type#} and any other data type
+ (e.g. a {#link|Primitive Type|Primitive Types#} or a user-defined type such as a {#link|struct#}, {#link|enum#}, or {#link|union#}).
The full form of an error union type is
- <error set type>{#syntax#}!{#endsyntax#}<primitive type>. In the code
+ <error set type>{#syntax#}!{#endsyntax#}<any data type>. In the code
sample, the error set type is not explicitly written on the left side of the {#syntax#}!{#endsyntax#} operator.
- When written this way, the error set type is a special kind of error union type that has an
- {#link|inferred error set type|Inferred Error Sets#}. The {#syntax#}void{#endsyntax#} after the {#syntax#}!{#endsyntax#} operator
- tells the compiler that the function will not return a value under normal circumstances (i.e. no errors occur).
+ When written this way, the error set type is an {#link|inferred error set type|Inferred Error Sets#}. The
+ {#syntax#}void{#endsyntax#} after the {#syntax#}!{#endsyntax#} operator
+ tells the compiler that the function will not return a value under normal circumstances (i.e. when no errors occur).
+
+ In Zig, a function's block of statements and expressions are surrounded by an open curly-brace { and
+ close curly-brace }. Inside of the {#syntax#}main{#endsyntax#} function are expressions that perform
+ the task of outputting Hello, world! to standard output.
- Note to experienced programmers: Zig also has the boolean {#link|operator|Operators#} {#syntax#}!a{#endsyntax#}
- where {#syntax#}a{#endsyntax#} is a value of type {#syntax#}bool{#endsyntax#}. Error union types contain the
- name of the type in the syntax: {#syntax#}!{#endsyntax#}<primitive type>.
-
- In Zig, a function's block of statements and expressions are surrounded by { and
- } curly-braces. Inside of the main function are expressions that perform
- the task of outputting Hello, world! to standard output.
-
- First, a constant identifier, stdout, is initialized to represent standard output's
- writer. Then, the program tries to print the Hello, world!
+ First, a constant identifier, {#syntax#}stdout{#endsyntax#}, is initialized to represent standard output's
+ writer. Then, the program tries to print the Hello, world!
message to standard output.
Functions sometimes need information to perform their task. In Zig, information is passed
- to functions between open ( and close ) parenthesis placed after
+ to functions between an open parenthesis {#syntax#}({#endsyntax#} and a close parenthesis {#syntax#}){#endsyntax#} placed after
the function's name. This information is also known as arguments. When there are
- multiple arguments passed to a function, they are separated by commas ,.
+ multiple arguments passed to a function, they are separated by commas {#syntax#},{#endsyntax#}.
- The two arguments passed to the stdout.print() function, "Hello, {s}!\n"
- and .{"world"}, are evaluated at {#link|compile-time|comptime#}. The code sample is
+ The two arguments passed to the {#syntax#}stdout.print(){#endsyntax#} function, {#syntax#}"Hello, {s}!\n"{#endsyntax#}
+ and {#syntax#}.{"world"}{#endsyntax#}, are evaluated at {#link|compile-time|comptime#}. The code sample is
purposely written to show how to perform {#link|string|String Literals and Unicode Code Point Literals#}
- substitution in the print function. The curly-braces inside of the first argument
+ substitution in the {#syntax#}print{#endsyntax#} function. The curly-braces inside of the first argument
are substituted with the compile-time known value inside of the second argument
(known as an {#link|anonymous struct literal|Anonymous Struct Literals#}). The \n
inside of the double-quotes of the first argument is the {#link|escape sequence|Escape Sequences#} for the
- newline character. The {#link|try#} expression evaluates the result of stdout.print.
+ newline character. The {#link|try#} expression evaluates the result of {#syntax#}stdout.print{#endsyntax#}.
If the result is an error, then the {#syntax#}try{#endsyntax#} expression will return from
- main with the error. Otherwise, the program will continue. In this case, there are no
- more statements or expressions left to execute in the main function, so the program exits.
+ {#syntax#}main{#endsyntax#} with the error. Otherwise, the program will continue. In this case, there are no
+ more statements or expressions left to execute in the {#syntax#}main{#endsyntax#} function, so the program exits.
- In Zig, the standard output writer's print function is allowed to fail because
+ In Zig, the standard output writer's {#syntax#}print{#endsyntax#} function is allowed to fail because
it is actually a function defined as part of a generic Writer. Consider a generic Writer that
represents writing data to a file. When the disk is full, a write to the file will fail.
However, we typically do not expect writing text to the standard output to fail. To avoid having
to handle the failure case of printing to standard output, you can use alternate functions: the
- functions in std.log for proper logging or the std.debug.print function.
+ functions in {#syntax#}std.log{#endsyntax#} for proper logging or the {#syntax#}std.debug.print{#endsyntax#} function.
This documentation will use the latter option to print to standard error (stderr) and silently return
- on failure. The next code sample, hello_again.zig demonstrates the use of
- std.debug.print.
+ on failure. The next code sample, hello_again.zig demonstrates the use of
+ {#syntax#}std.debug.print{#endsyntax#}.
- Note that you can leave off the {#syntax#}!{#endsyntax#} from the return type because std.debug.print cannot fail.
+ Note that you can leave off the {#syntax#}!{#endsyntax#} from the return type because {#syntax#}std.debug.print{#endsyntax#} cannot fail.
- zig test is a tool that can be used to quickly build and run Zig code
+ zig test is a tool that can be used to quickly build and run Zig code
to make sure behavior meets expectations. {#syntax#}@import("builtin").is_test{#endsyntax#}
is available for code to detect whether the current build is a test build.
See the rest of the {#syntax#}std.testing{#endsyntax#} namespace for more available functions.
- zig test has a few command line parameters which affect the compilation. See
- zig --help for a full list. The most interesting one is --test-filter [text].
+ zig test has a few command line parameters which affect the compilation. See
+ zig --help for a full list. The most interesting one is --test-filter [text].
This makes the test build only include tests whose name contains the supplied filter text.
Again, thanks to lazy analysis, this can allow you to narrow a build to only a few functions in
isolation.
| - Name - | -- C Equivalent - | -- Description - | +|||
|---|---|---|---|---|---|
| Type | +C Equivalent | +Description | |||
| {#syntax#}i8{#endsyntax#} | +{#syntax#}i8{#endsyntax#} | int8_t |
signed 8-bit integer | ||
| {#syntax#}u8{#endsyntax#} | +{#syntax#}u8{#endsyntax#} | uint8_t |
unsigned 8-bit integer | ||
| {#syntax#}i16{#endsyntax#} | +{#syntax#}i16{#endsyntax#} | int16_t |
signed 16-bit integer | ||
| {#syntax#}u16{#endsyntax#} | +{#syntax#}u16{#endsyntax#} | uint16_t |
unsigned 16-bit integer | ||
| {#syntax#}i32{#endsyntax#} | +{#syntax#}i32{#endsyntax#} | int32_t |
signed 32-bit integer | ||
| {#syntax#}u32{#endsyntax#} | +{#syntax#}u32{#endsyntax#} | uint32_t |
unsigned 32-bit integer | ||
| {#syntax#}i64{#endsyntax#} | +{#syntax#}i64{#endsyntax#} | int64_t |
signed 64-bit integer | ||
| {#syntax#}u64{#endsyntax#} | +{#syntax#}u64{#endsyntax#} | uint64_t |
unsigned 64-bit integer | ||
| {#syntax#}i128{#endsyntax#} | +{#syntax#}i128{#endsyntax#} | __int128 |
signed 128-bit integer | ||
| {#syntax#}u128{#endsyntax#} | +{#syntax#}u128{#endsyntax#} | unsigned __int128 |
unsigned 128-bit integer | ||
| {#syntax#}isize{#endsyntax#} | +{#syntax#}isize{#endsyntax#} | intptr_t |
signed pointer sized integer | ||
| {#syntax#}usize{#endsyntax#} | +{#syntax#}usize{#endsyntax#} | uintptr_t |
unsigned pointer sized integer | ||
| {#syntax#}c_short{#endsyntax#} | +{#syntax#}c_short{#endsyntax#} | short |
for ABI compatibility with C | ||
| {#syntax#}c_ushort{#endsyntax#} | +{#syntax#}c_ushort{#endsyntax#} | unsigned short |
for ABI compatibility with C | ||
| {#syntax#}c_int{#endsyntax#} | +{#syntax#}c_int{#endsyntax#} | int |
for ABI compatibility with C | ||
| {#syntax#}c_uint{#endsyntax#} | +{#syntax#}c_uint{#endsyntax#} | unsigned int |
for ABI compatibility with C | ||
| {#syntax#}c_long{#endsyntax#} | +{#syntax#}c_long{#endsyntax#} | long |
for ABI compatibility with C | ||
| {#syntax#}c_ulong{#endsyntax#} | +{#syntax#}c_ulong{#endsyntax#} | unsigned long |
for ABI compatibility with C | ||
| {#syntax#}c_longlong{#endsyntax#} | +{#syntax#}c_longlong{#endsyntax#} | long long |
for ABI compatibility with C | ||
| {#syntax#}c_ulonglong{#endsyntax#} | +{#syntax#}c_ulonglong{#endsyntax#} | unsigned long long |
for ABI compatibility with C | ||
| {#syntax#}c_longdouble{#endsyntax#} | +{#syntax#}c_longdouble{#endsyntax#} | long double |
for ABI compatibility with C | ||
| {#syntax#}c_void{#endsyntax#} | +{#syntax#}c_void{#endsyntax#} | void |
for ABI compatibility with C | ||
| {#syntax#}f16{#endsyntax#} | +{#syntax#}f16{#endsyntax#} | _Float16 |
16-bit floating point (10-bit mantissa) IEEE-754-2008 binary16 | ||
| {#syntax#}f32{#endsyntax#} | +{#syntax#}f32{#endsyntax#} | float |
32-bit floating point (23-bit mantissa) IEEE-754-2008 binary32 | ||
| {#syntax#}f64{#endsyntax#} | +{#syntax#}f64{#endsyntax#} | double |
64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64 | ||
| {#syntax#}f128{#endsyntax#} | +{#syntax#}f128{#endsyntax#} | _Float128 |
128-bit floating point (112-bit mantissa) IEEE-754-2008 binary128 | ||
| {#syntax#}bool{#endsyntax#} | +{#syntax#}bool{#endsyntax#} | bool |
{#syntax#}true{#endsyntax#} or {#syntax#}false{#endsyntax#} | ||
| {#syntax#}void{#endsyntax#} | +{#syntax#}void{#endsyntax#} | (none) | 0 bit type | ||
| {#syntax#}noreturn{#endsyntax#} | +{#syntax#}noreturn{#endsyntax#} | (none) | the type of {#syntax#}break{#endsyntax#}, {#syntax#}continue{#endsyntax#}, {#syntax#}return{#endsyntax#}, {#syntax#}unreachable{#endsyntax#}, and {#syntax#}while (true) {}{#endsyntax#} | ||
| {#syntax#}type{#endsyntax#} | +{#syntax#}type{#endsyntax#} | (none) | the type of types | ||
| {#syntax#}anyerror{#endsyntax#} | +{#syntax#}anyerror{#endsyntax#} | (none) | an error code | ||
| {#syntax#}comptime_int{#endsyntax#} | +{#syntax#}comptime_int{#endsyntax#} | (none) | Only allowed for {#link|comptime#}-known values. The type of integer literals. | ||
| {#syntax#}comptime_float{#endsyntax#} | +{#syntax#}comptime_float{#endsyntax#} | (none) | Only allowed for {#link|comptime#}-known values. The type of float literals. |
@@ -746,26 +845,27 @@ pub fn main() void { {#header_open|Primitive Values#}
| - Name - | -- Description - | +Name | +Description |
|---|---|---|---|
| {#syntax#}true{#endsyntax#} and {#syntax#}false{#endsyntax#} | +{#syntax#}true{#endsyntax#} and {#syntax#}false{#endsyntax#} | {#syntax#}bool{#endsyntax#} values | |
| {#syntax#}null{#endsyntax#} | +{#syntax#}null{#endsyntax#} | used to set an optional type to {#syntax#}null{#endsyntax#} | |
| {#syntax#}undefined{#endsyntax#} | +{#syntax#}undefined{#endsyntax#} | used to leave a value unspecified |
| - Escape Sequence - | -- Name - | +Escape Sequence | +Name |
|---|---|---|---|
\n |
+ \n |
Newline | |
\r |
+ \r |
Carriage Return | |
\t |
+ \t |
Tab | |
\\ |
+ \\ |
Backslash | |
\' |
+ \' |
Single Quote | |
\" |
+ \" |
Double Quote | |
\xNN |
+ \xNN |
hexadecimal 8-bit byte value (2 digits) | |
\u{NNNNNN} |
+ \u{NNNNNN} |
hexadecimal Unicode code point UTF-8 encoded (1 or more digits) |
Note that the maximum valid Unicode point is {#syntax#}0x10ffff{#endsyntax#}.
@@ -870,7 +971,7 @@ test "string literals" { However, if the next line begins with {#syntax#}\\{#endsyntax#} then a newline is appended and the string literal continues. - {#code_begin|syntax#} + {#code_begin|syntax|multiline_string_literals#} const hello_world_in_c = \\#include{#syntax#}const{#endsyntax#} applies to all of the bytes that the identifier immediately addresses. {#link|Pointers#} have their own const-ness.
If you need a variable that you can modify, use the {#syntax#}var{#endsyntax#} keyword:
- {#code_begin|test#} + {#code_begin|test|var_test#} const expect = @import("std").testing.expect; test "var" { @@ -923,7 +1024,7 @@ test "initialization" { {#code_end#} {#header_open|undefined#}Use {#syntax#}undefined{#endsyntax#} to leave variables uninitialized:
- {#code_begin|test#} + {#code_begin|test|undefined_test#} const expect = @import("std").testing.expect; test "init with undefined" { @@ -1108,7 +1209,7 @@ test "comptime vars" { {#header_open|Integers#} {#header_open|Integer Literals#} - {#code_begin|syntax#} + {#code_begin|syntax|integer_literals#} const decimal_int = 98222; const hex_int = 0xff; const another_hex_int = 0xFF; @@ -1131,7 +1232,7 @@ const big_address = 0xFF80_0000_0000_0000; However, once an integer value is no longer known at compile-time, it must have a known size, and is vulnerable to undefined behavior. - {#code_begin|syntax#} + {#code_begin|syntax|runtime_vs_comptime#} fn divide(a: i32, b: i32) i32 { return a / b; } @@ -1174,7 +1275,7 @@ fn divide(a: i32, b: i32) i32 { Float literals {#link|coerce|Type Coercion#} to any floating point type, and to any {#link|integer|Integers#} type when there is no fractional component. - {#code_begin|syntax#} + {#code_begin|syntax|float_literals#} const floating_point = 123.0E+77; const another_float = 123.0; const yet_another = 123.0e+77; @@ -1192,7 +1293,7 @@ const more_hex = 0x1234_5678.9ABC_CDEFp-10; There is no syntax for NaN, infinity, or negative infinity. For these special values, one must use the standard library: - {#code_begin|syntax#} + {#code_begin|syntax|float_special_values#} const std = @import("std"); const inf = std.math.inf(f32); @@ -1245,23 +1346,19 @@ pub fn main() void { {#header_open|Table of Operators#}| - Syntax - | -- Relevant Types - | -- Description - | -- Example - | +Syntax | +Relevant Types | +Description | +Example |
|---|---|---|---|---|---|---|---|
{#syntax#}a + b
-a += b{#endsyntax#} |
+ {#syntax#}a + b
+a += b{#endsyntax#} |
|
|||||
{#syntax#}a +% b
-a +%= b{#endsyntax#} |
+ {#syntax#}a +% b
+a +%= b{#endsyntax#} |
|
|||||
{#syntax#}a - b
-a -= b{#endsyntax#} |
+ {#syntax#}a - b
+a -= b{#endsyntax#} |
|
|||||
{#syntax#}a -% b
-a -%= b{#endsyntax#} |
+ {#syntax#}a -% b
+a -%= b{#endsyntax#} |
|
|||||
{#syntax#}-a{#endsyntax#} |
+ {#syntax#}-a{#endsyntax#} |
|
|||||
{#syntax#}-%a{#endsyntax#} |
+ {#syntax#}-%a{#endsyntax#} |
|
|||||
{#syntax#}a * b
-a *= b{#endsyntax#} |
+ {#syntax#}a * b
+a *= b{#endsyntax#} |
|
|||||
{#syntax#}a *% b
-a *%= b{#endsyntax#} |
+ {#syntax#}a *% b
+a *%= b{#endsyntax#} |
|
|||||
{#syntax#}a / b
-a /= b{#endsyntax#} |
+ {#syntax#}a / b
+a /= b{#endsyntax#} |
|
|||||
{#syntax#}a % b
-a %= b{#endsyntax#} |
+ {#syntax#}a % b
+a %= b{#endsyntax#} |
|
|||||
{#syntax#}a << b
-a <<= b{#endsyntax#} |
+ {#syntax#}a << b
+a <<= b{#endsyntax#} |
|
|||||
{#syntax#}a >> b
-a >>= b{#endsyntax#} |
+ {#syntax#}a >> b
+a >>= b{#endsyntax#} |
|
|||||
{#syntax#}a & b
-a &= b{#endsyntax#} |
+ {#syntax#}a & b
+a &= b{#endsyntax#} |
|
|||||
{#syntax#}a | b
-a |= b{#endsyntax#} |
+ {#syntax#}a | b
+a |= b{#endsyntax#} |
|
|||||
{#syntax#}a ^ b
-a ^= b{#endsyntax#} |
+ {#syntax#}a ^ b
+a ^= b{#endsyntax#} |
|
|||||
{#syntax#}~a{#endsyntax#} |
+ {#syntax#}~a{#endsyntax#} |
|
|||||
{#syntax#}a orelse b{#endsyntax#} |
+ {#syntax#}a orelse b{#endsyntax#} |
|
|||||
{#syntax#}a.?{#endsyntax#} |
+ {#syntax#}a.?{#endsyntax#} |
|
|||||
{#syntax#}a catch b
-a catch |err| b{#endsyntax#} |
+ {#syntax#}a catch b
+a catch |err| b{#endsyntax#} |
|
|||||
{#syntax#}a and b{#endsyntax#} |
+ {#syntax#}a and b{#endsyntax#} |
|
|||||
{#syntax#}a or b{#endsyntax#} |
+ {#syntax#}a or b{#endsyntax#} |
|
|||||
{#syntax#}!a{#endsyntax#} |
+ {#syntax#}!a{#endsyntax#} |
|
|||||
{#syntax#}a == b{#endsyntax#} |
+ {#syntax#}a == b{#endsyntax#} |
|
|||||
{#syntax#}a == null{#endsyntax#} |
+ {#syntax#}a == null{#endsyntax#} |
|
|||||
{#syntax#}a != b{#endsyntax#} |
+ {#syntax#}a != b{#endsyntax#} |
|
|||||
{#syntax#}a > b{#endsyntax#} |
+ {#syntax#}a > b{#endsyntax#} |
|
|||||
{#syntax#}a >= b{#endsyntax#} |
+ {#syntax#}a >= b{#endsyntax#} |
|
|||||
{#syntax#}a < b{#endsyntax#} |
+ {#syntax#}a < b{#endsyntax#} |
|
|||||
{#syntax#}a <= b{#endsyntax#} |
+ {#syntax#}a <= b{#endsyntax#} |
|
|||||
{#syntax#}a ++ b{#endsyntax#} |
+ {#syntax#}a ++ b{#endsyntax#} |
Array concatenation.
|
@@ -1798,7 +1895,7 @@ mem.eql(u32, &together, &[_]u32{1,2,3,4}){#endsyntax#}
|
| |||
{#syntax#}a ** b{#endsyntax#} |
+ {#syntax#}a ** b{#endsyntax#} |
Array multiplication.
|
@@ -1817,7 +1914,7 @@ mem.eql(u8, pattern, "ababab"){#endsyntax#}
|
| |||
{#syntax#}a.*{#endsyntax#} |
+ {#syntax#}a.*{#endsyntax#} |
|
|||||
{#syntax#}&a{#endsyntax#} |
+ {#syntax#}&a{#endsyntax#} |
All types | @@ -1847,7 +1944,7 @@ ptr.* == 1234{#endsyntax#}|||||
{#syntax#}a || b{#endsyntax#} |
+ {#syntax#}a || b{#endsyntax#} |
|
Use {#syntax#}&x{#endsyntax#} to obtain a single-item pointer:
- {#code_begin|test#} + {#code_begin|test|single_item_pointer_test#} const expect = @import("std").testing.expect; test "address of syntax" { @@ -2182,7 +2280,7 @@ test "pointer array access" { against this kind of undefined behavior. This is one reason we prefer slices to pointers. - {#code_begin|test#} + {#code_begin|test|slice_bounds#} const expect = @import("std").testing.expect; test "pointer slicing" { @@ -2197,7 +2295,7 @@ test "pointer slicing" { {#code_end#}Pointers work at compile-time too, as long as the code does not depend on an undefined memory layout:
- {#code_begin|test#} + {#code_begin|test|comptime_pointers#} const expect = @import("std").testing.expect; test "comptime pointers" { @@ -2212,7 +2310,7 @@ test "comptime pointers" { {#code_end#}To convert an integer address into a pointer, use {#syntax#}@intToPtr{#endsyntax#}. To convert a pointer to an integer, use {#syntax#}@ptrToInt{#endsyntax#}:
- {#code_begin|test#} + {#code_begin|test|integer_pointer_conversion#} const expect = @import("std").testing.expect; test "@ptrToInt and @intToPtr" { @@ -2224,7 +2322,7 @@ test "@ptrToInt and @intToPtr" { {#code_end#}Zig is able to preserve memory addresses in comptime code, as long as the pointer is never dereferenced:
- {#code_begin|test#} + {#code_begin|test|comptime_pointer_conversion#} const expect = @import("std").testing.expect; test "comptime @intToPtr" { @@ -2244,7 +2342,7 @@ test "comptime @intToPtr" { should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}. In the following code, loads and stores with {#syntax#}mmio_ptr{#endsyntax#} are guaranteed to all happen and in the same order as in source code: - {#code_begin|test#} + {#code_begin|test|volatile#} const expect = @import("std").testing.expect; test "volatile" { @@ -2263,7 +2361,7 @@ test "volatile" { operation that Zig cannot protect you against. Use {#syntax#}@ptrCast{#endsyntax#} only when other conversions are not possible. - {#code_begin|test#} + {#code_begin|test|pointer_casting#} const std = @import("std"); const expect = std.testing.expect; @@ -2301,7 +2399,7 @@ test "pointer child type" { In Zig, a pointer type has an alignment value. If the value is equal to the alignment of the underlying type, it can be omitted from the type: - {#code_begin|test#} + {#code_begin|test|variable_alignment#} const std = @import("std"); const expect = std.testing.expect; @@ -2323,7 +2421,7 @@ test "variable alignment" { You can specify alignment on variables and functions. If you do this, then pointers to them get the specified alignment: - {#code_begin|test#} + {#code_begin|test|variable_func_alignment#} const expect = @import("std").testing.expect; var foo: u8 align(4) = 100; @@ -2660,7 +2758,7 @@ test "linked list" { Each struct field may have an expression indicating the default field value. Such expressions are executed at {#link|comptime#}, and allow the field to be omitted in a struct literal expression: - {#code_begin|test#} + {#code_begin|test|default_field_values#} const Foo = struct { a: i32 = 1234, b: i32, @@ -2709,7 +2807,7 @@ test "default struct initialization fields" { in a {#link|@bitCast#} or a {#link|@ptrCast#} to reinterpret memory. This even works at {#link|comptime#}: - {#code_begin|test#} + {#code_begin|test|packed_structs#} const std = @import("std"); const native_endian = @import("builtin").target.cpu.arch.endian(); const expect = std.testing.expect; @@ -2750,7 +2848,7 @@ fn doTheTest() !void {Zig allows the address to be taken of a non-byte-aligned field:
- {#code_begin|test#} + {#code_begin|test|pointer_to_non-byte_aligned_field#} const std = @import("std"); const expect = std.testing.expect; @@ -2806,7 +2904,7 @@ fn bar(x: *const u3) u3 {Pointers to non-ABI-aligned fields share the same address as the other fields within their host integer:
- {#code_begin|test#} + {#code_begin|test|pointer_to_non-bit_aligned_field#} const std = @import("std"); const expect = std.testing.expect; @@ -2830,7 +2928,7 @@ test "pointer to non-bit-aligned field" {This can be observed with {#link|@bitOffsetOf#} and {#link|offsetOf#}:
- {#code_begin|test#} + {#code_begin|test|test_bitOffsetOf_offsetOf#} const std = @import("std"); const expect = std.testing.expect; @@ -2875,7 +2973,7 @@ test "overaligned pointer to packed struct" {It's also possible to set alignment of struct fields:
- {#code_begin|test#} + {#code_begin|test|test_aligned_struct_fields#} const std = @import("std"); const expectEqual = std.testing.expectEqual; @@ -3129,7 +3227,7 @@ export fn entry(foo: Foo) void { _ = foo; }Enum literals allow specifying the name of an enum field without specifying the enum type:
- {#code_begin|test#} + {#code_begin|test|test_enum_literals#} const std = @import("std"); const expect = std.testing.expect; @@ -3171,7 +3269,7 @@ test "switch using enum literals" { A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong with the difference being that it makes it a compile error if all the known tag names are not handled by the switch. - {#code_begin|test#} + {#code_begin|test|test_switch_non-exhaustive#} const std = @import("std"); const expect = std.testing.expect; @@ -3224,7 +3322,7 @@ test "simple union" { } {#code_end#}You can activate another field by assigning the entire union:
- {#code_begin|test#} + {#code_begin|test|test_simple_union#} const std = @import("std"); const expect = std.testing.expect; @@ -3253,7 +3351,7 @@ test "simple union" { to use with {#link|switch#} expressions. Tagged unions coerce to their tag type: {#link|Type Coercion: unions and enums#}. - {#code_begin|test#} + {#code_begin|test|test_switch_tagged_union#} const std = @import("std"); const expect = std.testing.expect; @@ -3291,7 +3389,7 @@ test "coerce to enum" {In order to modify the payload of a tagged union in a switch expression, place a {#syntax#}*{#endsyntax#} before the variable name to make it a pointer:
- {#code_begin|test#} + {#code_begin|test|test_switch_modify_tagged_union#} const std = @import("std"); const expect = std.testing.expect; @@ -3320,7 +3418,7 @@ test "modify tagged union in switch" { Unions can be made to infer the enum tag type. Further, unions can have methods just like structs and enums. - {#code_begin|test#} + {#code_begin|test|test_union_method#} const std = @import("std"); const expect = std.testing.expect; @@ -3352,7 +3450,7 @@ test "union method" { {#link|@tagName#} can be used to return a {#link|comptime#} {#syntax#}[:0]const u8{#endsyntax#} value representing the field name: - {#code_begin|test#} + {#code_begin|test|test_tagName#} const std = @import("std"); const expect = std.testing.expect; @@ -3377,7 +3475,7 @@ test "@tagName" { {#header_open|packed union#}A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible - to be in a {#link|packed struct#}. + to be in a {#link|packed struct#}.
{#header_close#} {#header_open|Anonymous Union Literals#} @@ -3448,7 +3546,7 @@ test "access variable after block scope" {Blocks are expressions. When labeled, {#syntax#}break{#endsyntax#} can be used to return a value from the block:
- {#code_begin|test#} + {#code_begin|test|test_labeled_break#} const std = @import("std"); const expect = std.testing.expect; @@ -3482,7 +3580,7 @@ test "inside test block" { Because of this, when you read Zig code you can rely on an identifier always meaning the same thing, within the scope it is defined. Note that you can, however use the same name if the scopes are separate: - {#code_begin|test#} + {#code_begin|test|test_scopes#} test "separate scopes" { { const pi = 3.14; @@ -3569,7 +3667,7 @@ test "switch inside function" { done by placing a {#syntax#}*{#endsyntax#} before the capture variable name, turning it into a pointer. - {#code_begin|test#} + {#code_begin|test|test_switch_tagged_union#} const expect = @import("std").testing.expect; test "switch on tagged union" { @@ -3636,7 +3734,7 @@ test "exhaustive switching" { {#link|Enum Literals#} can be useful to use with {#syntax#}switch{#endsyntax#} to avoid repetitively specifying {#link|enum#} or {#link|union#} types: - {#code_begin|test#} + {#code_begin|test|test_exhaustive_switch#} const std = @import("std"); const expect = std.testing.expect; @@ -3761,7 +3859,7 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) bool { {#header_open|Labeled while#}When a {#syntax#}while{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#} or {#syntax#}continue{#endsyntax#} from within a nested loop:
- {#code_begin|test#} + {#code_begin|test|test_nested_break#} test "nested break" { outer: while (true) { while (true) { @@ -3866,7 +3964,7 @@ fn eventuallyErrorSequence() anyerror!u32 { allows the code to do some things which only work at compile time, such as use types as first class values. - {#code_begin|test#} + {#code_begin|test|test_inline_while#} const expect = @import("std").testing.expect; test "inline while loop" { @@ -3969,7 +4067,7 @@ test "for else" { {#header_open|Labeled for#}When a {#syntax#}for{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#} or {#syntax#}continue{#endsyntax#} from within a nested loop:
- {#code_begin|test#} + {#code_begin|test|test_nested_break#} const std = @import("std"); const expect = std.testing.expect; @@ -4005,7 +4103,7 @@ test "nested continue" { The capture value and iterator value of inlined for loops are compile-time known. - {#code_begin|test#} + {#code_begin|test|test_inline_loop#} const expect = @import("std").testing.expect; test "inline for loop" { @@ -4278,16 +4376,16 @@ test "errdefer unwinding" { {#header_close#} {#header_open|unreachable#}
- In {#syntax#}Debug{#endsyntax#} and {#syntax#}ReleaseSafe{#endsyntax#} mode, and when using zig test,
+ In {#syntax#}Debug{#endsyntax#} and {#syntax#}ReleaseSafe{#endsyntax#} mode, and when using zig test,
{#syntax#}unreachable{#endsyntax#} emits a call to {#syntax#}panic{#endsyntax#} with the message reached unreachable code.
In {#syntax#}ReleaseFast{#endsyntax#} mode, the optimizer uses the assumption that {#syntax#}unreachable{#endsyntax#} code
- will never be hit to perform optimizations. However, zig test even in {#syntax#}ReleaseFast{#endsyntax#} mode
+ will never be hit to perform optimizations. However, zig test even in {#syntax#}ReleaseFast{#endsyntax#} mode
still emits {#syntax#}unreachable{#endsyntax#} as calls to {#syntax#}panic{#endsyntax#}.
When resolving types together, such as {#syntax#}if{#endsyntax#} clauses or {#syntax#}switch{#endsyntax#} prongs, the {#syntax#}noreturn{#endsyntax#} type is compatible with every other type. Consider:
- {#code_begin|test#} + {#code_begin|test|test_noreturn#} fn foo(condition: bool, b: u32) void { const a = if (condition) b else return; _ = a; @@ -4354,7 +4452,7 @@ test "noreturn" { } {#code_end#}Another use case for {#syntax#}noreturn{#endsyntax#} is the {#syntax#}exit{#endsyntax#} function:
- {#code_begin|test#} + {#code_begin|test|noreturn_from_exit#} {#target_windows#} pub extern "kernel32" fn ExitProcess(exit_code: c_uint) callconv(if (@import("builtin").target.cpu.arch == .i386) .Stdcall else .C) noreturn; @@ -4451,7 +4549,7 @@ fn foo() void { } as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable. - {#code_begin|test#} + {#code_begin|test|pass_by_reference_or_value#} const Point = struct { x: i32, y: i32, @@ -4481,7 +4579,7 @@ test "pass struct to function" { In this case the parameter types will be inferred when the function is called. Use {#link|@TypeOf#} and {#link|@typeInfo#} to get information about the inferred type. - {#code_begin|test#} + {#code_begin|test|test_fn_type_inference#} const expect = @import("std").testing.expect; fn addFortyTwo(x: anytype) @TypeOf(x) { @@ -4499,7 +4597,7 @@ test "fn type inference" { {#header_close#} {#header_open|Function Reflection#} - {#code_begin|test#} + {#code_begin|test|test_fn_reflection#} const expect = @import("std").testing.expect; test "fn reflection" { @@ -4524,7 +4622,7 @@ test "fn reflection" {You can {#link|coerce|Type Coercion#} an error from a subset to a superset:
- {#code_begin|test#} + {#code_begin|test|coercing_subset_to_superset#} const std = @import("std"); const FileOpenError = error { @@ -4608,7 +4706,7 @@ const err = (error {FileNotFound}).FileNotFound;Here is a function to parse a string into a 64-bit integer:
- {#code_begin|test#} + {#code_begin|test|error_union_parsing_u64#} const std = @import("std"); const maxInt = std.math.maxInt; @@ -4791,7 +4889,7 @@ fn createFoo(param: i32) !Foo {An error union is created with the {#syntax#}!{#endsyntax#} binary operator. You can use compile-time reflection to access the child type of an error union:
- {#code_begin|test#} + {#code_begin|test|test_error_union#} const expect = @import("std").testing.expect; test "error union" { @@ -4823,7 +4921,7 @@ test "error union" { {#syntax#}LinuxFileOpenError || WindowsFileOpenError{#endsyntax#} for the error set of opening files. - {#code_begin|test#} + {#code_begin|test|test_merging_error_sets#} const A = error{ NotDir, @@ -4859,7 +4957,7 @@ test "merge error sets" { Because many functions in Zig return a possible error, Zig supports inferring the error set. To infer the error set for a function, use this syntax: -{#code_begin|test#} +{#code_begin|test|inferred_error_sets#} // With an inferred error set pub fn add_inferred(comptime T: type, a: T, b: T) !T { var answer: T = undefined; @@ -5173,7 +5271,7 @@ fn doAThing(optional_foo: ?*Foo) void { {#header_open|Optional Type#}An optional is created by putting {#syntax#}?{#endsyntax#} in front of a type. You can use compile-time reflection to access the child type of an optional:
- {#code_begin|test#} + {#code_begin|test|test_optional_type#} const expect = @import("std").testing.expect; test "optional type" { @@ -5200,7 +5298,7 @@ const optional_value: ?i32 = null; {#header_open|Optional Pointers#}An optional pointer is guaranteed to be the same size as a pointer. The {#syntax#}null{#endsyntax#} of the optional is guaranteed to be address 0.
- {#code_begin|test#} + {#code_begin|test|test_optional_pointer#} const expect = @import("std").testing.expect; test "optional pointers" { @@ -5232,7 +5330,7 @@ test "optional pointers" {Type coercion occurs when one type is expected, but different type is provided:
- {#code_begin|test#} + {#code_begin|test|type_coercion#} test "type coercion - variable declaration" { var a: u8 = 1; var b: u16 = a; @@ -5272,7 +5370,7 @@ test "type coercion - @as builtin" {These casts are no-ops at runtime since the value representation does not change.
- {#code_begin|test#} + {#code_begin|test|no_op_casts#} test "type coercion - const qualification" { var a: i32 = 1; var b: *i32 = &a; @@ -5284,7 +5382,7 @@ fn foo(_: *const i32) void {}In addition, pointers coerce to const optional pointers:
- {#code_begin|test#} + {#code_begin|test|pointer_coerce_const_optional#} const std = @import("std"); const expect = std.testing.expect; const mem = std.mem; @@ -5301,7 +5399,7 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" { {#link|Integers#} coerce to integer types which can represent every value of the old type, and likewise {#link|Floats#} coerce to float types which can represent every value of the old type. - {#code_begin|test#} + {#code_begin|test|test_integer_widening#} const std = @import("std"); const expect = std.testing.expect; const mem = std.mem; @@ -5429,7 +5527,7 @@ test "*T to *[1]T" {The payload type of {#link|Optionals#}, as well as {#link|null#}, coerce to the optional type.
- {#code_begin|test#} + {#code_begin|test|test_coerce_optionals#} const std = @import("std"); const expect = std.testing.expect; @@ -5442,7 +5540,7 @@ test "coerce to optionals" { } {#code_end#}It works nested inside the {#link|Error Union Type#}, too:
- {#code_begin|test#} + {#code_begin|test|test_corerce_optional_wrapped_error_union#} const std = @import("std"); const expect = std.testing.expect; @@ -5459,7 +5557,7 @@ test "coerce to optionals wrapped in error union" {The payload type of an {#link|Error Union Type#} as well as the {#link|Error Set Type#} coerce to the error union type:
- {#code_begin|test#} + {#code_begin|test|test_coerce_to_error_union#} const std = @import("std"); const expect = std.testing.expect; @@ -5476,7 +5574,7 @@ test "coercion to error unions" {When a number is {#link|comptime#}-known to be representable in the destination type, it may be coerced:
- {#code_begin|test#} + {#code_begin|test|test_coerce_large_to_small#} const std = @import("std"); const expect = std.testing.expect; @@ -5492,7 +5590,7 @@ test "coercing large integer type to smaller one when value is comptime known to when they are {#link|comptime#}-known to be a field of the union that has only one possible value, such as {#link|void#}: - {#code_begin|test#} + {#code_begin|test|test_coerce_unions_enums#} const std = @import("std"); const expect = std.testing.expect; @@ -5525,7 +5623,7 @@ test "coercion between unions and enums" { regardless of const.TODO document the reasoning for this
TODO document whether vice versa should work and why
- {#code_begin|test#} + {#code_begin|test|coerce_zero_bit_types#} test "coercion of zero bit types" { var x: void = {}; var y: *void = x; @@ -5715,7 +5813,7 @@ export fn entry() void { {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#} type to make it into a {#syntax#}Set{#endsyntax#}: - {#code_begin|test#} + {#code_begin|test|void_in_hashmap#} const std = @import("std"); const expect = std.testing.expect; @@ -5755,7 +5853,7 @@ fn foo() i32 { } {#code_end#}However, if the expression has type {#syntax#}void{#endsyntax#}, there will be no error. Function return values can also be explicitly ignored by assigning them to {#syntax#}_{#endsyntax#}.
- {#code_begin|test#} + {#code_begin|test|void_ignored#} test "void is ignored" { returnsVoid(); } @@ -5774,7 +5872,7 @@ fn foo() i32 { {#header_open|Pointers to Zero Bit Types#}Pointers to zero bit types also have zero bits. They always compare equal to each other:
- {#code_begin|test#} + {#code_begin|test|pointers_to_zero_bits#} const std = @import("std"); const expect = std.testing.expect; @@ -5812,36 +5910,24 @@ test "@intToPtr for pointer to zero bit type" { {#header_open|usingnamespace#}- {#syntax#}usingnamespace{#endsyntax#} is a declaration that imports all the public declarations of - the operand, which must be a {#link|struct#}, {#link|union#}, or {#link|enum#}, into the current scope: + {#syntax#}usingnamespace{#endsyntax#} is a declaration that mixes all the public + declarations of the operand, which must be a {#link|struct#}, {#link|union#}, {#link|enum#}, + or {#link|opaque#}, into the namespace:
{#code_begin|test|usingnamespace#} -usingnamespace @import("std"); - test "using std namespace" { - try testing.expect(true); -} - {#code_end#} -- {#syntax#}usingnamespace{#endsyntax#} can also be used in containers: -
- {#code_begin|test|usingnamespace_inside_struct#} -test "using namespace inside struct" { - const L = struct { - usingnamespace struct { - pub fn f() void {} - }; + const S = struct { + usingnamespace @import("std"); }; - L.f(); + try S.testing.expect(true); } {#code_end#}
- Instead of the above pattern, it is generally recommended to explicitly alias individual declarations.
- However, {#syntax#}usingnamespace{#endsyntax#} has an important use case when organizing the public
- API of a file or package. For example, one might have c.zig with all of the
+ {#syntax#}usingnamespace{#endsyntax#} has an important use case when organizing the public
+ API of a file or package. For example, one might have c.zig with all of the
{#link|C imports|Import from C Header File#}:
{#syntax#}
+ {#syntax_block|zig|c.zig#}
pub usingnamespace @cImport({
@cInclude("epoxy/gl.h");
@cInclude("GLFW/glfw3.h");
@@ -5849,7 +5935,7 @@ pub usingnamespace @cImport({
@cDefine("STBI_NO_STDIO", "");
@cInclude("stb_image.h");
});
- {#endsyntax#}
+ {#end_syntax_block#}
The above example demonstrates using {#syntax#}pub{#endsyntax#} to qualify the {#syntax#}usingnamespace{#endsyntax#} additionally makes the imported declarations @@ -5858,6 +5944,7 @@ pub usingnamespace @cImport({
{#header_close#} + {#header_open|comptime#}Zig places importance on the concept of whether an expression is known at compile-time. @@ -5934,7 +6021,7 @@ test "try to compare bools" { value is known at compile-time. This means that we actually could make this work for the bool type if we wanted to:
- {#code_begin|test#} + {#code_begin|test|comptime_max_with_bool#} fn max(comptime T: type, a: T, b: T) T { if (T == bool) { return a or b; @@ -6097,7 +6184,7 @@ test "foo" {Let's look at an example:
- {#code_begin|test#} + {#code_begin|test|fibonacci_recursion#} const expect = @import("std").testing.expect; fn fibonacci(index: u32) u32 { @@ -6190,7 +6277,7 @@ test "fibonacci" { {#syntax#}comptime{#endsyntax#} expressions. This means that we can use functions to initialize complex static data. For example: - {#code_begin|test#} + {#code_begin|test|N_primes#} const first_25_primes = firstNPrimes(25); const sum_of_first_25_primes = sum(&first_25_primes); @@ -6491,7 +6578,7 @@ pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {Dissecting the syntax:
-{#syntax#}// Inline assembly is an expression which returns a value.
+ {#syntax_block|zig|Assembly Syntax Explained#}// Inline assembly is an expression which returns a value.
// the `asm` keyword begins the expression.
_ = asm
// `volatile` is an optional modifier that tells Zig this
@@ -6546,7 +6633,7 @@ volatile (
// output. In this example we list $rcx and $r11 because it is known the
// kernel syscall does not preserve these registers.
: "rcx", "r11"
-);{#endsyntax#}
+);{#end_syntax_block#}
For i386 and x86_64 targets, the syntax is AT&T syntax, rather than the more popular Intel syntax. This is due to technical constraints; assembly parsing is @@ -6672,7 +6759,7 @@ test "global assembly" { return to the callsite (in the case of the first suspension), or resumer (in the case of subsequent suspensions).
- {#code_begin|test#} + {#code_begin|test|suspend_no_resume#} const std = @import("std"); const expect = std.testing.expect; @@ -6699,7 +6786,7 @@ fn func() void { {#syntax#}resume{#endsyntax#} operation on a different thread. {#link|@frame#} provides access to the async function frame pointer. - {#code_begin|test#} + {#code_begin|test|async_suspend_block#} const std = @import("std"); const expect = std.testing.expect; @@ -6737,7 +6824,7 @@ fn testSuspendBlock() void { However, the async function can be directly resumed from the suspend block, in which case it never returns to its resumer and continues executing. - {#code_begin|test#} + {#code_begin|test|resume_from_suspend#} const std = @import("std"); const expect = std.testing.expect; @@ -6773,7 +6860,7 @@ fn testResumeFromSuspend(my_result: *i32) void { execution would continue at the most recent {#syntax#}async{#endsyntax#} callsite or {#syntax#}resume{#endsyntax#} callsite, and the return value of the async function would be lost. - {#code_begin|test#} + {#code_begin|test|async_await#} const std = @import("std"); const expect = std.testing.expect; @@ -6817,7 +6904,7 @@ fn func() void { does not suspend; instead it copies the return value directly from the target function's frame. - {#code_begin|test#} + {#code_begin|test|async_await_sequence#} const std = @import("std"); const expect = std.testing.expect; @@ -7031,6 +7118,16 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 { If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. {#header_close#} + {#header_open|@addWithSaturation#} +{#syntax#}@addWithSaturation(a: T, b: T) T{#endsyntax#}
+ + Returns {#syntax#}a + b{#endsyntax#}. The result will be clamped between the type maximum and minimum. +
++ Once Saturating arithmetic. + is completed, the syntax {#syntax#}a +| b{#endsyntax#} will be equivalent to calling {#syntax#}@addWithSaturation(a, b){#endsyntax#}. +
+ {#header_close#} {#header_open|@alignCast#}{#syntax#}@alignCast(comptime alignment: u29, ptr: anytype) anytype{#endsyntax#}
@@ -7085,7 +7182,7 @@ comptime { read after {#link|await|Async and Await#} completes. Any result location provided to {#syntax#}await{#endsyntax#} will copy the result from {#syntax#}result_ptr{#endsyntax#}.
- {#code_begin|test#} + {#code_begin|test|async_struct_field_fn_pointer#} const std = @import("std"); const expect = std.testing.expect; @@ -7527,7 +7624,7 @@ test "main" { not encountered by analysis, the program compiles successfully and the generated executable prints: - {#code_begin|test#} + {#code_begin|test|without_compileLog#} const print = @import("std").debug.print; const num1 = blk: { @@ -7759,7 +7856,7 @@ export fn @"A function name that is a complete sentence."() void {}{#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}
Performs field access by a compile-time string. Works on both fields and declarations.
- {#code_begin|test#} + {#code_begin|test|field_decl_access_by_string#} const std = @import("std"); const Point = struct { @@ -7844,7 +7941,7 @@ test "decl access by string" { This type is suitable to be used as the return type of {#link|async|Async and Await#} which allows one to, for example, heap-allocate an async function frame: - {#code_begin|test#} + {#code_begin|test|heap_allocated_frame#} const std = @import("std"); test "heap allocated frame" { @@ -7890,7 +7987,7 @@ fn func() void { Returns whether or not a {#link|struct#}, {#link|enum#}, or {#link|union#} has a declaration matching {#syntax#}name{#endsyntax#}. - {#code_begin|test#} + {#code_begin|test|hasDecl#} const std = @import("std"); const expect = std.testing.expect; @@ -8105,7 +8202,7 @@ mem.set(u8, dest, c);{#endsyntax#} designers targeting Wasm. So unless you are writing a new allocator from scratch, you should use something like {#syntax#}@import("std").heap.WasmPageAllocator{#endsyntax#}. - {#code_begin|test#} + {#code_begin|test|wasmMemoryGrow#} const std = @import("std"); const native_arch = @import("builtin").target.cpu.arch; const expect = std.testing.expect; @@ -8143,6 +8240,22 @@ test "@wasmMemoryGrow" { If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. {#header_close#} + + {#header_open|@mulWithSaturation#} +{#syntax#}@mulWithSaturation(a: T, b: T) T{#endsyntax#}
+ + Returns {#syntax#}a * b{#endsyntax#}. The result will be clamped between the type maximum and minimum. +
++ Once Saturating arithmetic. + is completed, the syntax {#syntax#}a *| b{#endsyntax#} will be equivalent to calling {#syntax#}@mulWithSaturation(a, b){#endsyntax#}. +
++ NOTE: Currently there is a bug in the llvm.smul.fix.sat intrinsic which affects {#syntax#}@mulWithSaturation{#endsyntax#} of signed integers. + This may result in an incorrect sign bit when there is overflow. This will be fixed in zig's 0.9.0 release. + Check this issue for more information. +
+ {#header_close#} {#header_open|@panic#}{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}
@@ -8276,7 +8389,7 @@ test "foo" {
}
{#code_end#}
Now we use {#syntax#}@setEvalBranchQuota{#endsyntax#}:
- {#code_begin|test#} + {#code_begin|test|setEvalBranchQuota#} test "foo" { comptime { @setEvalBranchQuota(1001); @@ -8368,7 +8481,7 @@ test "@setRuntimeSafety" { The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits. This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior. - {#see_also|@shrExact|@shlWithOverflow#} + {#see_also|@shrExact|@shlWithOverflow|@shlWithSaturation#} {#header_close#} {#header_open|@shlWithOverflow#} @@ -8382,7 +8495,22 @@ test "@setRuntimeSafety" { The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits. This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior. - {#see_also|@shlExact|@shrExact#} + {#see_also|@shlExact|@shrExact|@shlWithSaturation#} + {#header_close#} + + {#header_open|@shlWithSaturation#} +{#syntax#}@shlWithSaturation(a: T, shift_amt: T) T{#endsyntax#}
+ + Returns {#syntax#}a << b{#endsyntax#}. The result will be clamped between type minimum and maximum. +
++ Once Saturating arithmetic. + is completed, the syntax {#syntax#}a <<| b{#endsyntax#} will be equivalent to calling {#syntax#}@shlWithSaturation(a, b){#endsyntax#}. +
++ Unlike other @shl builtins, shift_amt doesn't need to be a Log2T as saturated overshifting is well defined. +
+ {#see_also|@shlExact|@shrExact|@shlWithOverflow#} {#header_close#} {#header_open|@shrExact#} @@ -8395,7 +8523,7 @@ test "@setRuntimeSafety" { The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits. This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior. - {#see_also|@shlExact|@shlWithOverflow#} + {#see_also|@shlExact|@shlWithOverflow|@shlWithSaturation#} {#header_close#} {#header_open|@shuffle#} @@ -8460,7 +8588,7 @@ test "@setRuntimeSafety" { Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value {#syntax#}scalar{#endsyntax#}: - {#code_begin|test#} + {#code_begin|test|vector_splat#} const std = @import("std"); const expect = std.testing.expect; @@ -8494,7 +8622,7 @@ test "vector @splat" {Note that {#syntax#}.Add{#endsyntax#} and {#syntax#}.Mul{#endsyntax#} @@ -8502,7 +8630,7 @@ test "vector @splat" { types the operation associativity is preserved, unless the float mode is set to {#syntax#}Optimized{#endsyntax#}.
- {#code_begin|test#} + {#code_begin|test|vector_reduce#} const std = @import("std"); const expect = std.testing.expect; @@ -8524,7 +8652,7 @@ test "vector @reduce" {Returns a {#syntax#}SourceLocation{#endsyntax#} struct representing the function's name and location in the source code. This must be called in a function.
- {#code_begin|test#} + {#code_begin|test|source_location#} const std = @import("std"); const expect = std.testing.expect; @@ -8538,7 +8666,7 @@ fn doTheTest() !void { try expect(src.line == 9); try expect(src.column == 17); try expect(std.mem.endsWith(u8, src.fn_name, "doTheTest")); - try expect(std.mem.endsWith(u8, src.file, "test.zig")); + try expect(std.mem.endsWith(u8, src.file, "source_location.zig")); } {#code_end#} {#header_close#} @@ -8694,6 +8822,17 @@ fn doTheTest() !void { If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}. {#header_close#} + + {#header_open|@subWithSaturation#} +{#syntax#}@subWithSaturation(a: T, b: T) T{#endsyntax#}
+ + Returns {#syntax#}a - b{#endsyntax#}. The result will be clamped between the type maximum and minimum. +
++ Once Saturating arithmetic. + is completed, the syntax {#syntax#}a -| b{#endsyntax#} will be equivalent to calling {#syntax#}@subWithSaturation(a, b){#endsyntax#}. +
+ {#header_close#} {#header_open|@tagName#}{#syntax#}@tagName(value: anytype) [:0]const u8{#endsyntax#}
@@ -8708,7 +8847,7 @@ fn doTheTest() !void {
Returns the innermost struct, enum, or union that this function call is inside.
This can be useful for an anonymous struct that needs to refer to itself:
- {#code_begin|test#}
+ {#code_begin|test|this_innermost#}
const std = @import("std");
const expect = std.testing.expect;
@@ -8843,7 +8982,7 @@ test "integer truncation" {
The expressions are evaluated, however they are guaranteed to have no runtime side-effects:
- {#code_begin|test#} + {#code_begin|test|no_runtime_side_effects#} const std = @import("std"); const expect = std.testing.expect; @@ -8884,9 +9023,9 @@ fn foo(comptime T: type, ptr: *T) T {
- To add standard build options to a build.zig file:
+ To add standard build options to a build.zig file:
This causes these options to be available:
- -Drelease-safe=[bool] optimizations on and safety on
- -Drelease-fast=[bool] optimizations on and safety off
- -Drelease-small=[bool] size optimizations on and safety off
+ -
+
- -Drelease-safe=[bool]
- Optimizations on and safety on +
- -Drelease-fast=[bool]
- Optimizations on and safety off +
- -Drelease-small=[bool]
- Size optimizations on and safety off +
$ zig build-exe example.zig
+ {#shell_samp#}$ zig build-exe example.zig{#end_shell_samp#}
- Fast compilation speed
- Safety checks enabled @@ -8912,7 +9053,7 @@ pub fn build(b: *Builder) void {
$ zig build-exe example.zig -O ReleaseFast
+ {#shell_samp#}$ zig build-exe example.zig -O ReleaseFast{#end_shell_samp#}
- Fast runtime performance
- Safety checks disabled @@ -8922,7 +9063,7 @@ pub fn build(b: *Builder) void {
$ zig build-exe example.zig -O ReleaseSafe
+ {#shell_samp#}$ zig build-exe example.zig -O ReleaseSafe{#end_shell_samp#}
- Medium runtime performance
- Safety checks enabled @@ -8932,7 +9073,7 @@ pub fn build(b: *Builder) void {
$ zig build-exe example.zig -O ReleaseSmall
+ {#shell_samp#}$ zig build-exe example.zig -O ReleaseSmall{#end_shell_samp#}
- Medium runtime performance
- Safety checks disabled @@ -8945,7 +9086,7 @@ pub fn build(b: *Builder) void { {#header_close#} {#header_open|Single Threaded Builds#} -
- All {#link|Thread Local Variables#} are treated as regular {#link|Container Level Variables#}.
- The overhead of {#link|Async Functions#} becomes equivalent to function call overhead. @@ -9156,7 +9297,7 @@ pub fn main() void {
- {#syntax#}-%{#endsyntax#} (wraparound negation)
- {#syntax#}*%{#endsyntax#} (wraparound multiplication)
- Custom tasks.
Zig has a compile option --single-threaded which has the following effects:
Zig has a compile option --single-threaded which has the following effects:
- To use the build system, run zig build --help
+ To use the build system, run zig build --help
to see a command-line usage help menu. This will include project-specific
options that were declared in the build.zig script.
This build.zig file is automatically generated
- by zig init-exe.
This build.zig file is automatically generated
+ by zig init-exe.
This build.zig file is automatically generated
- by zig init-lib.
This build.zig file is automatically generated
+ by zig init-lib.
The {#syntax#}@cImport{#endsyntax#} builtin function can be used
- to directly import symbols from .h files:
+ to directly import symbols from .h files:
The {#syntax#}@cImport{#endsyntax#} function takes an expression as a parameter.
This expression is evaluated at compile-time and is used to control
- preprocessor directives and include multiple .h files:
+ preprocessor directives and include multiple .h files:
zig translate-c.
+ Zig's C translation capability is available as a CLI tool via zig translate-c.
It requires a single filename as an argument. It may also take a set of optional flags that are
forwarded to clang. It writes the translated file to stdout.
{#header_open|Command line flags#}
-
-
-I: + -I: Specify a search directory for include files. May be used multiple times. Equivalent to - clang's-Iflag. The current directory is not included by default; - use-I.to include it. + clang's -I flag. The current directory is not included by default; + use -I. to include it. -
-
-D: Define a preprocessor macro. Equivalent to + -D: Define a preprocessor macro. Equivalent to - clang's-Dflag. + clang's -D flag. -
-
-cflags [flags] --: Pass arbitrary additional + -cflags [flags] --: Pass arbitrary additional command line - flags to clang. Note: the list of flags must end with--+ flags to clang. Note: the list of flags must end with -- -
-
-target: The {#link|target triple|Targets#} for the translated Zig code. + -target: The {#link|target triple|Targets#} for the translated Zig code. If no target is specified, the current host target will be used.
- Important! When translating C code with zig translate-c,
- you must use the same -target triple that you will use when compiling
- the translated code. In addition, you must ensure that the -cflags used,
- if any, match the cflags used by code on the target system. Using the incorrect -target
- or -cflags could result in clang or Zig parse failures, or subtle ABI incompatibilities
+ Important! When translating C code with zig translate-c,
+ you must use the same -target triple that you will use when compiling
+ the translated code. In addition, you must ensure that the -cflags used,
+ if any, match the cflags used by code on the target system. Using the incorrect -target
+ or -cflags could result in clang or Zig parse failures, or subtle ABI incompatibilities
when linking with C code.
varytarget.h
-long FOO = __LONG_MAX__;
- $ zig translate-c -target thumb-freestanding-gnueabihf varytarget.h|grep FOO
-pub export var FOO: c_long = 2147483647;
- $ zig translate-c -target x86_64-macos-gnu varytarget.h|grep FOO
-pub export var FOO: c_long = 9223372036854775807;
- varycflags.h
-enum FOO { BAR };
-int do_something(enum FOO foo);
- $ zig translate-c varycflags.h|grep -B1 do_something
-pub const enum_FOO = c_uint;
-pub extern fn do_something(foo: enum_FOO) c_int;
- $ zig translate-c -cflags -fshort-enums -- varycflags.h|grep -B1 do_something
-pub const enum_FOO = u8;
-pub extern fn do_something(foo: enum_FOO) c_int;
+ {#syntax_block|c|varytarget.h#}long FOO = __LONG_MAX__;{#end_syntax_block#}
+ {#shell_samp#}$ zig translate-c -target thumb-freestanding-gnueabihf varytarget.h|grep FOO
+pub export var FOO: c_long = 2147483647;
+$ zig translate-c -target x86_64-macos-gnu varytarget.h|grep FOO
+pub export var FOO: c_long = 9223372036854775807;{#end_shell_samp#}
+ {#syntax_block|c|varycflags.h#}enum FOO { BAR };
+int do_something(enum FOO foo);
+ {#end_syntax_block#}
+ {#shell_samp#}$ zig translate-c varycflags.h|grep -B1 do_something
+pub const enum_FOO = c_uint;
+pub extern fn do_something(foo: enum_FOO) c_int;
+$ zig translate-c -cflags -fshort-enums -- varycflags.h|grep -B1 do_something
+pub const enum_FOO = u8;
+pub extern fn do_something(foo: enum_FOO) c_int;{#end_shell_samp#}
{#header_close#}
{#header_open|@cImport vs translate-c#}
- {#syntax#}@cImport{#endsyntax#} and zig translate-c use the same underlying
+
{#syntax#}@cImport{#endsyntax#} and zig translate-c use the same underlying
C translation functionality, so on a technical level they are equivalent. In practice,
{#syntax#}@cImport{#endsyntax#} is useful as a way to quickly and easily access numeric constants, typedefs,
and record types without needing any extra setup. If you need to pass {#link|cflags|Using -target and -cflags#}
to clang, or if you would like to edit the translated code, it is recommended to use
- zig translate-c and save the results to a file. Common reasons for editing
+ zig translate-c and save the results to a file. Common reasons for editing
the generated code include: changing {#syntax#}anytype{#endsyntax#} parameters in function-like macros to more
specific types; changing {#syntax#}[*c]T{#endsyntax#} pointers to {#syntax#}[*]T{#endsyntax#} or
{#syntax#}*T{#endsyntax#} pointers for improved type safety; and
@@ -10101,14 +10241,14 @@ pub extern fn do_something(foo: enum_FOO) c_int;
{#header_close#}
{#header_open|C Translation Caching#}
- The C translation feature (whether used via zig translate-c or
+ The C translation feature (whether used via zig translate-c or
{#syntax#}@cImport{#endsyntax#}) integrates with the Zig caching system. Subsequent runs with
the same source file, target, and cflags will use the cache instead of repeatedly translating
the same code.
To see where the cached files are stored when compiling code that uses {#syntax#}@cImport{#endsyntax#},
- use the --verbose-cimport flag:
+ use the --verbose-cimport flag:
- cimport.h contains the file to translate (constructed from calls to
+ cimport.h contains the file to translate (constructed from calls to
{#syntax#}@cInclude{#endsyntax#}, {#syntax#}@cDefine{#endsyntax#}, and {#syntax#}@cUndef{#endsyntax#}),
- cimport.h.d is the list of file dependencies, and
- cimport.zig contains the translated output.
+ cimport.h.d is the list of file dependencies, and
+ cimport.zig contains the translated output.
Consider the following example:
-macro.c
-#define MAKELOCAL(NAME, INIT) int NAME = INIT
+ {#syntax_block|c|macro.c#}#define MAKELOCAL(NAME, INIT) int NAME = INIT
int foo(void) {
MAKELOCAL(a, 1);
MAKELOCAL(b, 2);
return a + b;
-}
-$ zig translate-c macro.c > macro.zig
-
- macro.zig
-{#syntax#}pub export fn foo() c_int {
+}
+ {#end_syntax_block#}
+ {#shell_samp#}$ zig translate-c macro.c > macro.zig{#end_shell_samp#}
+ {#code_begin|syntax|macro#}
+pub export fn foo() c_int {
var a: c_int = 1;
var b: c_int = 2;
return a + b;
}
-pub const MAKELOCAL = @compileError("unable to translate C expr: unexpected token .Equal"); // macro.c:1:9{#endsyntax#}
+pub const MAKELOCAL = @compileError("unable to translate C expr: unexpected token .Equal"); // macro.c:1:9
+ {#code_end#}
Note that {#syntax#}foo{#endsyntax#} was translated correctly despite using a non-translateable macro. {#syntax#}MAKELOCAL{#endsyntax#} was demoted to {#syntax#}@compileError{#endsyntax#} since it cannot be expressed as a Zig function; this simply means that you cannot directly use @@ -10231,31 +10371,27 @@ pub const MAKELOCAL = @compileError("unable to translate C expr: unexpected toke to call into. The {#syntax#}export{#endsyntax#} keyword in front of functions, variables, and types causes them to be part of the library API:
-mathtest.zig
- {#code_begin|syntax#} + {#code_begin|syntax|mathtest#} export fn add(a: i32, b: i32) i32 { return a + b; } {#code_end#}To make a static library:
-$ zig build-lib mathtest.zig
-
+ {#shell_samp#}$ zig build-lib mathtest.zig{#end_shell_samp#}
To make a shared library:
-$ zig build-lib mathtest.zig -dynamic
-
+ {#shell_samp#}$ zig build-lib mathtest.zig -dynamic{#end_shell_samp#}
Here is an example with the {#link|Zig Build System#}:
-test.c
-// This header is generated by zig from mathtest.zig
+ {#syntax_block|c|test.c#}// This header is generated by zig from mathtest.zig
#include "mathtest.h"
-#include <stdio.h>
+#include
int main(int argc, char **argv) {
int32_t result = add(42, 1337);
printf("%d\n", result);
return 0;
-}
- build.zig
- {#code_begin|syntax#} +} + {#end_syntax_block#} + {#code_begin|syntax|build#} const Builder = @import("std").build.Builder; pub fn build(b: *Builder) void { @@ -10274,18 +10410,15 @@ pub fn build(b: *Builder) void { test_step.dependOn(&run_cmd.step); } {#code_end#} -terminal
-$ zig build test
-1379
-
+ {#shell_samp#}$ zig build test
+1379{#end_shell_samp#}
{#see_also|export#}
{#header_close#}
{#header_open|Mixing Object Files#}
You can mix Zig object files with any other object files that respect the C ABI. Example:
-base64.zig
- {#code_begin|syntax#} + {#code_begin|syntax|base64#} const base64 = @import("std").base64; export fn decode_base_64( @@ -10302,12 +10435,11 @@ export fn decode_base_64( return decoded_size; } {#code_end#} -test.c
-// This header is generated by zig from base64.zig
+ {#syntax_block|c|test.c#}// This header is generated by zig from base64.zig
#include "base64.h"
-#include <string.h>
-#include <stdio.h>
+#include
+#include
int main(int argc, char **argv) {
const char *encoded = "YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz";
@@ -10318,9 +10450,9 @@ int main(int argc, char **argv) {
puts(buf);
return 0;
-}
- build.zig
- {#code_begin|syntax#} +} + {#end_syntax_block#} + {#code_begin|syntax|build#} const Builder = @import("std").build.Builder; pub fn build(b: *Builder) void { @@ -10333,10 +10465,9 @@ pub fn build(b: *Builder) void { exe.install(); } {#code_end#} -terminal
-$ zig build
+ {#shell_samp#}$ zig build
$ ./zig-out/bin/test
-all your base are belong to us
+all your base are belong to us{#end_shell_samp#}
{#see_also|Targets|Zig Build System#}
{#header_close#}
{#header_close#}
@@ -10354,9 +10485,7 @@ export fn add(a: i32, b: i32) void {
print(a + b);
}
{#code_end#}
- {#header_close#}
- test.js
-const fs = require('fs');
+ {#syntax_block|javascript|test.js#}const fs = require('fs');
const source = fs.readFileSync("./math.wasm");
const typedArray = new Uint8Array(source);
@@ -10366,9 +10495,10 @@ WebAssembly.instantiate(typedArray, {
}}).then(result => {
const add = result.instance.exports.add;
add(1, 2);
-});
- $ node test.js
-The result is 3
+});{#end_syntax_block#}
+ {#shell_samp#}$ node test.js
+The result is 3{#end_shell_samp#}
+ {#header_close#}
{#header_open|WASI#}
Zig's support for WebAssembly System Interface (WASI) is under active development. Example of using the standard library and reading command line arguments:
@@ -10387,10 +10517,10 @@ pub fn main() !void { } } {#code_end#} -$ wasmtime args.wasm 123 hello
+ {#shell_samp#}$ wasmtime args.wasm 123 hello
0: args.wasm
1: 123
-2: hello
+2: hello{#end_shell_samp#}
A more interesting example would be extracting the list of preopens from the runtime. This is now supported in the standard library via {#syntax#}std.fs.wasi.PreopenList{#endsyntax#}:
{#code_begin|exe|preopens#} @@ -10412,9 +10542,9 @@ pub fn main() !void { } } {#code_end#} -$ wasmtime --dir=. preopens.wasm
+ {#shell_samp#}$ wasmtime --dir=. preopens.wasm
0: Preopen{ .fd = 3, .type = PreopenType{ .Dir = '.' } }
-
+ {#end_shell_samp#}
{#header_close#}
{#header_close#}
{#header_open|Targets#}
@@ -10423,7 +10553,7 @@ pub fn main() !void {
what it looks like to execute zig targets on a Linux x86_64
computer:
- $ zig targets
+ {#shell_samp#}$ zig targets
Architectures:
arm
v8_4a
@@ -10660,7 +10790,7 @@ Available libcs:
wasm32-wasi-musl
x86_64-linux-gnu
x86_64-linux-gnux32
- x86_64-linux-musl
+ x86_64-linux-musl{#end_shell_samp#}
The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating system abstractions, and thus takes additional work to support more platforms. @@ -10730,9 +10860,9 @@ coding style.
File names fall into two categories: types and namespaces. If the file
(implicitly a struct) has top level fields, it should be named like any
- other struct with fields using {#syntax#}TitleCase{#endsyntax#}. Otherwise,
- it should use {#syntax#}snake_case{#endsyntax#}. Directory names should be
- {#syntax#}snake_case{#endsyntax#}.
+ other struct with fields using TitleCase. Otherwise,
+ it should use snake_case. Directory names should be
+ snake_case.
These are general rules of thumb; if it makes sense to do something different, @@ -10741,7 +10871,7 @@ coding style.
{#header_close#} {#header_open|Examples#} -{#syntax#}
+ {#syntax_block|zig|style_example.zig#}
const namespace_name = @import("dir_name/file_name.zig");
const TypeName = @import("dir_name/TypeName.zig");
var global_var: i32 = undefined;
@@ -10785,9 +10915,9 @@ const XmlParser = struct {
// The initials BE (Big Endian) are just another word in Zig identifier names.
fn readU32Be() u32 {}
- {#endsyntax#}
+ {#end_syntax_block#}
- See the Zig Standard Library for more examples. + See the {#link|Zig Standard Library#} for more examples.
{#header_close#} {#header_open|Doc Comment Guidance#} @@ -10822,7 +10952,7 @@ fn readU32Be() u32 {} but use of hard tabs is discouraged. See {#link|Grammar#}.
- Note that running zig fmt on a source file will implement all recommendations mentioned here.
+ Note that running zig fmt on a source file will implement all recommendations mentioned here.
Note also that the stage1 compiler does not yet support CR or HT control characters.
@@ -10840,18 +10970,18 @@ fn readU32Be() u32 {} {#header_open|Keyword Reference#}
| - Keyword - | -- Description - | +Keyword | +Description |
|---|---|---|---|
| + |
{#syntax#}align{#endsyntax#}
-
+ |
{#syntax#}align{#endsyntax#} can be used to specify the alignment of a pointer. It can also be used after a variable or function declaration to specify the alignment of pointers to that variable or function. @@ -10861,9 +10991,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}allowzero{#endsyntax#}
-
+ |
The pointer attribute {#syntax#}allowzero{#endsyntax#} allows a pointer to have address zero.
|
|
| + |
{#syntax#}and{#endsyntax#}
-
+ |
The boolean operator {#syntax#}and{#endsyntax#}.
|
|
| + |
{#syntax#}anyframe{#endsyntax#}
-
+ |
{#syntax#}anyframe{#endsyntax#} can be used as a type for variables which hold pointers to function frames.
|
|
| + |
{#syntax#}anytype{#endsyntax#}
-
+ |
Function parameters and struct fields can be declared with {#syntax#}anytype{#endsyntax#} in place of the type. The type will be inferred where the function is called or the struct is instantiated. @@ -10906,9 +11036,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}asm{#endsyntax#}
-
+ |
{#syntax#}asm{#endsyntax#} begins an inline assembly expression. This allows for directly controlling the machine code generated on compilation.
|
|
| + |
{#syntax#}async{#endsyntax#}
-
+ |
{#syntax#}async{#endsyntax#} can be used before a function call to get a pointer to the function's frame when it suspends.
|
|
| + |
{#syntax#}await{#endsyntax#}
-
+ |
{#syntax#}await{#endsyntax#} can be used to suspend the current function until the frame provided after the {#syntax#}await{#endsyntax#} completes. {#syntax#}await{#endsyntax#} copies the value returned from the target function's frame to the caller. @@ -10940,9 +11070,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}break{#endsyntax#}
-
+ |
{#syntax#}break{#endsyntax#} can be used with a block label to return a value from the block. It can also be used to exit a loop before iteration completes naturally. @@ -10952,9 +11082,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}catch{#endsyntax#}
-
+ |
{#syntax#}catch{#endsyntax#} can be used to evaluate an expression if the expression before it evaluates to an error. The expression after the {#syntax#}catch{#endsyntax#} can optionally capture the error value. @@ -10964,9 +11094,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}comptime{#endsyntax#}
-
+ |
{#syntax#}comptime{#endsyntax#} before a declaration can be used to label variables or function parameters as known at compile time. It can also be used to guarantee an expression is run at compile time. @@ -10976,9 +11106,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}const{#endsyntax#}
-
+ |
{#syntax#}const{#endsyntax#} declares a variable that can not be modified. Used as a pointer attribute, it denotes the value referenced by the pointer cannot be modified. @@ -10988,9 +11118,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}continue{#endsyntax#}
-
+ |
{#syntax#}continue{#endsyntax#} can be used in a loop to jump back to the beginning of the loop.
|
|
| + |
{#syntax#}defer{#endsyntax#}
-
+ |
{#syntax#}defer{#endsyntax#} will execute an expression when control flow leaves the current block.
|
|
| + |
{#syntax#}else{#endsyntax#}
-
+ |
{#syntax#}else{#endsyntax#} can be used to provide an alternate branch for {#syntax#}if{#endsyntax#}, {#syntax#}switch{#endsyntax#}, {#syntax#}while{#endsyntax#}, and {#syntax#}for{#endsyntax#} expressions. @@ -11025,9 +11155,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}enum{#endsyntax#}
-
+ |
{#syntax#}enum{#endsyntax#} defines an enum type.
|
|
| + |
{#syntax#}errdefer{#endsyntax#}
-
+ |
{#syntax#}errdefer{#endsyntax#} will execute an expression when control flow leaves the current block if the function returns an error.
|
|
| + |
{#syntax#}error{#endsyntax#}
-
+ |
{#syntax#}error{#endsyntax#} defines an error type.
|
|
| + |
{#syntax#}export{#endsyntax#}
-
+ |
{#syntax#}export{#endsyntax#} makes a function or variable externally visible in the generated object file. Exported functions default to the C calling convention. @@ -11070,9 +11200,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}extern{#endsyntax#}
-
+ |
{#syntax#}extern{#endsyntax#} can be used to declare a function or variable that will be resolved at link time, when linking statically or at runtime, when linking dynamically. @@ -11082,9 +11212,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}false{#endsyntax#}
-
+ |
The boolean value {#syntax#}false{#endsyntax#}.
|
|
| + |
{#syntax#}fn{#endsyntax#}
-
+ |
{#syntax#}fn{#endsyntax#} declares a function.
|
|
| + |
{#syntax#}for{#endsyntax#}
-
+ |
A {#syntax#}for{#endsyntax#} expression can be used to iterate over the elements of a slice, array, or tuple.
|
|
| + |
{#syntax#}if{#endsyntax#}
-
+ |
An {#syntax#}if{#endsyntax#} expression can test boolean expressions, optional values, or error unions. For optional values or error unions, the if expression can capture the unwrapped value. @@ -11127,9 +11257,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}inline{#endsyntax#}
-
+ |
{#syntax#}inline{#endsyntax#} can be used to label a loop expression such that it will be unrolled at compile time. It can also be used to force a function to be inlined at all call sites. @@ -11139,9 +11269,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}noalias{#endsyntax#}
-
+ |
The {#syntax#}noalias{#endsyntax#} keyword.
|
|
| + |
{#syntax#}nosuspend{#endsyntax#}
-
+ |
The {#syntax#}nosuspend{#endsyntax#} keyword can be used in front of a block, statement or expression, to mark a scope where no suspension points are reached. In particular, inside a {#syntax#}nosuspend{#endsyntax#} scope: @@ -11168,9 +11298,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}null{#endsyntax#}
-
+ |
The optional value {#syntax#}null{#endsyntax#}.
|
|
| + |
{#syntax#}or{#endsyntax#}
-
+ |
The boolean operator {#syntax#}or{#endsyntax#}.
|
|
| + |
{#syntax#}orelse{#endsyntax#}
-
+ |
{#syntax#}orelse{#endsyntax#} can be used to evaluate an expression if the expression before it evaluates to null.
|
|
| + |
{#syntax#}packed{#endsyntax#}
-
+ |
The {#syntax#}packed{#endsyntax#} keyword before a struct definition changes the struct's in-memory layout to the guaranteed {#syntax#}packed{#endsyntax#} layout. @@ -11213,9 +11343,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}pub{#endsyntax#}
-
+ |
The {#syntax#}pub{#endsyntax#} in front of a top level declaration makes the declaration available to reference from a different file than the one it is declared in. @@ -11225,9 +11355,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}resume{#endsyntax#}
-
+ |
{#syntax#}resume{#endsyntax#} will continue execution of a function frame after the point the function was suspended.
|
|
| + |
{#syntax#}return{#endsyntax#}
-
+ |
{#syntax#}return{#endsyntax#} exits a function with a value.
|
|
| + |
{#syntax#}linksection{#endsyntax#}
-
+ |
The {#syntax#}linksection{#endsyntax#} keyword.
|
|
| + |
{#syntax#}struct{#endsyntax#}
-
+ |
{#syntax#}struct{#endsyntax#} defines a struct.
|
|
| + |
{#syntax#}suspend{#endsyntax#}
-
+ |
{#syntax#}suspend{#endsyntax#} will cause control flow to return to the call site or resumer of the function. {#syntax#}suspend{#endsyntax#} can also be used before a block within a function, @@ -11282,9 +11412,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}switch{#endsyntax#}
-
+ |
A {#syntax#}switch{#endsyntax#} expression can be used to test values of a common type. {#syntax#}switch{#endsyntax#} cases can capture field values of a {#link|Tagged union#}. @@ -11294,9 +11424,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}test{#endsyntax#}
-
+ |
The {#syntax#}test{#endsyntax#} keyword can be used to denote a top-level block of code used to make sure behavior meets expectations. @@ -11306,9 +11436,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}threadlocal{#endsyntax#}
-
+ |
{#syntax#}threadlocal{#endsyntax#} can be used to specify a variable as thread-local.
|
|
| + |
{#syntax#}true{#endsyntax#}
-
+ |
The boolean value {#syntax#}true{#endsyntax#}.
|
|
| + |
{#syntax#}try{#endsyntax#}
-
+ |
{#syntax#}try{#endsyntax#} evaluates an error union expression. If it is an error, it returns from the current function with the same error. @@ -11341,9 +11471,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}undefined{#endsyntax#}
-
+ |
{#syntax#}undefined{#endsyntax#} can be used to leave a value uninitialized.
|
|
| + |
{#syntax#}union{#endsyntax#}
-
+ |
{#syntax#}union{#endsyntax#} defines a union.
|
|
| + |
{#syntax#}unreachable{#endsyntax#}
-
+ |
{#syntax#}unreachable{#endsyntax#} can be used to assert that control flow will never happen upon a particular location.
Depending on the build mode, {#syntax#}unreachable{#endsyntax#} may emit a panic.
|
|
| + |
{#syntax#}usingnamespace{#endsyntax#}
-
+ |
{#syntax#}usingnamespace{#endsyntax#} is a top-level declaration that imports all the public declarations of the operand, which must be a struct, union, or enum, into the current scope. @@ -11389,9 +11519,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}var{#endsyntax#}
-
+ |
{#syntax#}var{#endsyntax#} declares a variable that may be modified.
|
|
| + |
{#syntax#}volatile{#endsyntax#}
-
+ |
{#syntax#}volatile{#endsyntax#} can be used to denote loads or stores of a pointer have side effects. It can also modify an inline assembly expression to denote it has side effects. @@ -11412,9 +11542,9 @@ fn readU32Be() u32 {} | |
| + |
{#syntax#}while{#endsyntax#}
-
+ |
A {#syntax#}while{#endsyntax#} expression can be used to repeatedly test a boolean, optional, or error union expression, and cease looping when that expression evaluates to false, null, or an error, respectively. @@ -11423,6 +11553,7 @@ fn readU32Be() u32 {} |