### Build and run print example Source: https://ziglang.org/documentation/0.15.2 Commands to compile and execute the print example. ```shell $ `zig build-exe print.zig` $ `./print` here is a string: 'foobar' here is a number: 1234 ``` -------------------------------- ### Build and Run Inline Assembly Example Source: https://ziglang.org/documentation/0.15.2 Commands to compile and execute the inline assembly example on x86_64 Linux. ```shell $ `zig build-exe inline_assembly.zig -target x86_64-linux` $ `./inline_assembly` hello world ``` -------------------------------- ### Run struct tests Source: https://ziglang.org/documentation/0.15.2 Command to execute the tests defined in the struct example file. ```shell $ `zig test test_structs.zig` 1/4 test_structs.test.dot product...OK 2/4 test_structs.test.struct namespaced variable...OK 3/4 test_structs.test.field parent pointer...OK 4/4 test_structs.test.linked list...OK All 4 tests passed. ``` -------------------------------- ### Implement Hello World with Inline Assembly Source: https://ziglang.org/documentation/0.15.2 A complete example demonstrating how to perform system calls on x86_64 Linux using Zig's inline assembly. ```zig pub fn main() noreturn { const msg = "hello world\n"; _ = syscall3(SYS_write, STDOUT_FILENO, @intFromPtr(msg), msg.len); _ = syscall1(SYS_exit, 0); unreachable; } pub const SYS_write = 1; pub const SYS_exit = 60; pub const STDOUT_FILENO = 1; pub fn syscall1(number: usize, arg1: usize) usize { return asm volatile ("syscall" : [ret] "={rax}" (-> usize), : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), : .{ .rcx = true, .r11 = true }); } pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { return asm volatile ("syscall" : [ret] "={rax}" (-> usize), : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3), : .{ .rcx = true, .r11 = true }); } ``` -------------------------------- ### Use @cImport with C headers Source: https://ziglang.org/documentation/0.15.2 Example of importing standard C headers using @cImport and @cDefine. ```zig const c = @cImport({ @cDefine("_NO_CRT_STDIO_INLINE", "1"); @cInclude("stdio.h"); }); pub fn main() void { _ = c; } ``` -------------------------------- ### Example: String Literals and Unicode Source: https://ziglang.org/documentation/0.15.2 A practical Zig code example demonstrating the usage of string literals, including accessing their length, individual bytes, and handling Unicode characters and non-UTF-8 byte sequences. It also shows how to compare byte arrays. ```APIDOC ## Example: String Literals and Unicode ```zig const print = @import("std").debug.print; const mem = @import("std").mem; // will be used to compare bytes pub fn main() void { const bytes = "hello"; print("{}\n", .{@TypeOf(bytes)}); print("{d}\n", .{bytes.len}); print("{c}\n", .{bytes[1]}); print("{d}\n", .{bytes[5]}); print("{} ", .{'e' == '\x65'}); print("{d}\n", .{'\u{1f4a9}'}); print("{d}\n", .{'💯'}); print("{u}\n", .{'⚡'}); print("{} ", .{mem.eql(u8, "hello", "h\x65llo")}); print("{} ", .{mem.eql(u8, "💯", "\xf0\x9f\x92\xaf")}); const invalid_utf8 = "\xff\xfe"; // non-UTF-8 strings are possible with \xNN notation. print("0x{x}\n", .{invalid_utf8[1]}); // indexing them returns individual bytes... print("0x{x}\n", .{"💯"[1]}); // ...as does indexing part-way through non-ASCII characters } ``` ### Shell Output ```shell $ `zig build-exe string_literals.zig` $ `./string_literals` *const [5:0]u8 5 e 0 true 128169 128175 ⚡ true true 0xfe 0x9f ``` ``` -------------------------------- ### Multiline String Literal Example Source: https://ziglang.org/documentation/0.15.2 Demonstrates creating a multiline string literal in Zig using the '\\' token. Newlines are not included unless the next line also starts with '\\'. ```zig const hello_world_in_c = \#include \ \int main(int argc, char **argv) { \ printf("hello world\n"); \ return 0; \} ; ``` -------------------------------- ### Zig Hello World with Formatted Printing Source: https://ziglang.org/documentation/0.15.2 A 'Hello, World!' example using `std.debug.print` for formatted output. The `!` can be omitted from the return type if the function does not return errors. ```zig const std = @import("std"); pub fn main() void { std.debug.print("Hello, {s}!\n", .{"World"); } ``` -------------------------------- ### Type Coercion Examples in Zig Source: https://ziglang.org/documentation/0.15.2 Demonstrates type coercion in Zig for variable declarations, function calls, and using the `@as` builtin. These examples show safe and unambiguous type conversions. ```zig test "type coercion - variable declaration" { const a: u8 = 1; const b: u16 = a; _ = b; } test "type coercion - function call" { const a: u8 = 1; foo(a); } fn foo(b: u16) void { _ = b; } test "type coercion - @as builtin" { const a: u8 = 1; const b = @as(u16, a); _ = b; } ``` -------------------------------- ### Global Assembly Example Source: https://ziglang.org/documentation/0.15.2 Demonstrates the usage of global assembly within a Zig comptime block. This assembly code is directly embedded and assembled. ```APIDOC ## Global Assembly When an assembly expression occurs in a container level comptime block, this is **global assembly**. This kind of assembly has different rules than inline assembly. First, `volatile` is not valid because all global assembly is unconditionally included. Second, there are no inputs, outputs, or clobbers. All global assembly is concatenated verbatim into one long string and assembled together. There are no template substitution rules regarding `%` as there are in inline assembly expressions. ### Example: test_global_assembly.zig ```zig const std = @import("std"); const expect = std.testing.expect; comptime { asm ( \.global my_func; \.type my_func, @function; \my_func: \ lea (%rdi,%rsi,1),%eax \ retq ); } extern fn my_func(a: i32, b: i32) i32; test "global assembly" { try expect(my_func(12, 34) == 46); } ``` ### Execution Example ```shell $ `zig test test_global_assembly.zig -target x86_64-linux -fllvm` 1/1 test_global_assembly.test.global assembly...OK All 1 tests passed. ``` ``` -------------------------------- ### Zig Test Execution Source: https://ziglang.org/documentation/0.15.2 Command to run Zig tests. This example shows how to execute the tests defined in `test_comptime_evaluation.zig`. ```shell $ `zig test test_comptime_evaluation.zig` 1/1 test_comptime_evaluation.test.perform fn...OK All 1 tests passed. ``` -------------------------------- ### Zig Comptime Variables Example Source: https://ziglang.org/documentation/0.15.2 Demonstrates the difference between regular local variables and `comptime` variables. `comptime` variables are evaluated during semantic analysis, allowing for compile-time checks and optimizations. ```zig const std = @import("std"); const expect = std.testing.expect; test "comptime vars" { var x: i32 = 1; comptime var y: i32 = 1; x += 1; y += 1; try expect(x == 2); try expect(y == 2); if (y != 2) { // This compile error never triggers because y is a comptime variable, // and so `y != 2` is a comptime value, and this if is statically evaluated. @compileError("wrong y value"); } } ``` -------------------------------- ### Translate C macros to Zig Source: https://ziglang.org/documentation/0.15.2 Example showing how C macros are handled during translation, including demotion to @compileError. ```c #define MAKELOCAL(NAME, INIT) int NAME = INIT int foo(void) { MAKELOCAL(a, 1); MAKELOCAL(b, 2); return a + b; } ``` ```shell $ `zig translate-c macro.c > macro.zig` ``` ```zig pub export fn foo() c_int { var a: c_int = 1; _ = &a; var b: c_int = 2; _ = &b; return a + b; } pub const MAKELOCAL = @compileError("unable to translate C expr: unexpected token .Equal"); // macro.c:1:9 ``` -------------------------------- ### Zig Comments Example Source: https://ziglang.org/documentation/0.15.2 Demonstrates single-line comments (`//`) in Zig. Doc comments and top-level doc comments are used for generating package documentation. ```zig const print = @import("std").debug.print; pub fn main() void { // Comments in Zig start with "//" and end at the next LF byte (end of line). // The line below is a comment and won't be executed. //print("Hello?", .{}); print("Hello, world!\n", .{}); // another comment } ``` -------------------------------- ### Initialize Static Data with Comptime Functions in Zig Source: https://ziglang.org/documentation/0.15.2 Use comptime functions to initialize complex static data at compile time. This example calculates prime numbers and their sum. ```zig const first_25_primes = firstNPrimes(25); const sum_of_first_25_primes = sum(&first_25_primes); fn firstNPrimes(comptime n: usize) [n]i32 { var prime_list: [n]i32 = undefined; var next_index: usize = 0; var test_number: i32 = 2; while (next_index < prime_list.len) : (test_number += 1) { var test_prime_index: usize = 0; var is_prime = true; while (test_prime_index < next_index) : (test_prime_index += 1) { if (test_number % prime_list[test_prime_index] == 0) { is_prime = false; break; } } if (is_prime) { prime_list[next_index] = test_number; next_index += 1; } } return prime_list; } fn sum(numbers: []const i32) i32 { var result: i32 = 0; for (numbers) |x| { result += x; } return result; } test "variable values" { try @import("std").testing.expect(sum_of_first_25_primes == 1060); } ``` -------------------------------- ### Run Zig test via shell Source: https://ziglang.org/documentation/0.15.2 Command to execute the test suite for the parsing example. ```shell $ `zig test error_union_parsing_u64.zig` 1/1 error_union_parsing_u64.test.parse u64...OK All 1 tests passed. ``` -------------------------------- ### Destructuring Vectors in Zig Source: https://ziglang.org/documentation/0.15.2 Demonstrates how to destructure vectors to extract individual elements or specific elements for rearrangement. This example emulates the `punpckldq` instruction. ```zig const print = @import("std").debug.print; // emulate punpckldq pub fn unpack(x: @Vector(4, f32), y: @Vector(4, f32)) @Vector(4, f32) { const a, const c, _, _ = x; const b, const d, _, _ = y; return .{ a, b, c, d }; } pub fn main() void { const x: @Vector(4, f32) = .{ 1.0, 2.0, 3.0, 4.0 }; const y: @Vector(4, f32) = .{ 5.0, 6.0, 7.0, 8.0 }; print("{}", .{unpack(x, y)}); } ``` -------------------------------- ### Zig program to list WASI preopens Source: https://ziglang.org/documentation/0.15.2 A Zig program that lists available WASI preopens. It uses `std.fs.wasi.preopensAlloc` to get a list of preopened file descriptors. Requires WASI target and a runtime that supports preopens (e.g., wasmtime --dir). ```zig const std = @import("std"); const fs = std.fs; pub fn main() !void { var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .init; const gpa = general_purpose_allocator.allocator(); var arena_instance = std.heap.ArenaAllocator.init(gpa); defer arena_instance.deinit(); const arena = arena_instance.allocator(); const preopens = try fs.wasi.preopensAlloc(arena); for (preopens.names, 0..) |preopen, i| { std.debug.print("{}: {s}\n", .{ i, preopen }); } } ``` -------------------------------- ### Testing Container Level Variables Source: https://ziglang.org/documentation/0.15.2 Shell command to test the container level variables example. It confirms that all tests passed. ```shell $ `zig test test_container_level_variables.zig` 1/1 test_container_level_variables.test.container level variables...OK All 1 tests passed. ``` -------------------------------- ### Declare and Export Functions in Zig Source: https://ziglang.org/documentation/0.15.2 Demonstrates function declaration, export specifier for C ABI compatibility, and extern specifier for external library functions. Includes examples of calling conventions like 'winapi' and 'cold'. ```zig const std = @import("std"); const builtin = @import("builtin"); const native_arch = builtin.cpu.arch; const expect = std.testing.expect; // Functions are declared like this fn add(a: i8, b: i8) i8 { if (a == 0) { return b; } return a + b; } // The export specifier makes a function externally visible in the generated // object file, and makes it use the C ABI. export fn sub(a: i8, b: i8) i8 { return a - b; } // The extern specifier is used to declare a function that will be resolved // at link time, when linking statically, or at runtime, when linking // dynamically. The quoted identifier after the extern keyword specifies // the library that has the function. (e.g. "c" -> libc.so) // The callconv specifier changes the calling convention of the function. extern "kernel32" fn ExitProcess(exit_code: u32) callconv(.winapi) noreturn; extern "c" fn atan2(a: f64, b: f64) f64; // The @branchHint builtin can be used to tell the optimizer that a function is rarely called ("cold"). fn abort() noreturn { @branchHint(.cold); while (true) {} } // The naked calling convention makes a function not have any function prologue or epilogue. // This can be useful when integrating with assembly. fn _start() callconv(.naked) noreturn { abort(); } // The inline calling convention forces a function to be inlined at all call sites. // If the function cannot be inlined, it is a compile-time error. inline fn shiftLeftOne(a: u32) u32 { return a << 1; } // The pub specifier allows the function to be visible when importing. // Another file can use @import and call sub2 pub fn sub2(a: i8, b: i8) i8 { return a - b; } // Function pointers are prefixed with `*const `. const Call2Op = *const fn (a: i8, b: i8) i8; fn doOp(fnCall: Call2Op, op1: i8, op2: i8) i8 { return fnCall(op1, op2); } test "function" { try expect(doOp(add, 5, 6) == 11); try expect(doOp(sub2, 5, 6) == -1); } ``` -------------------------------- ### Example of Built-in Package Contents Source: https://ziglang.org/documentation/0.15.2 The 'builtin' package provides a comprehensive set of compile-time constants. These include Zig version, backend, output mode, target details, and build configurations. Prefer feature detection over version checks for compatibility. ```zig const std = @import("std"); /// Zig version. When writing code that supports multiple versions of Zig, prefer /// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks. pub const zig_version = std.SemanticVersion.parse(zig_version_string) catch unreachable; pub const zig_version_string = "0.15.2"; pub const zig_backend = std.builtin.CompilerBackend.stage2_x86_64; pub const output_mode: std.builtin.OutputMode = .Exe; pub const link_mode: std.builtin.LinkMode = .static; pub const unwind_tables: std.builtin.UnwindTables = .async; pub const is_test = false; pub const single_threaded = false; pub const abi: std.Target.Abi = .gnu; pub const cpu: std.Target.Cpu = .{ .arch = .x86_64, .model = &std.Target.x86.cpu.znver4, .features = std.Target.x86.featureSet(&.{ ."64bit", .adx, .aes, .allow_light_256_bit, .avx, .avx2, .avx512bf16, .avx512bitalg, .avx512bw, .avx512cd, .avx512dq, .avx512f, .avx512ifma, .avx512vbmi, .avx512vbmi2, .avx512vl, .avx512vnni, .avx512vpopcntdq, .bmi, .bmi2, .branchfusion, .clflushopt, .clwb, .clzero, .cmov, .crc32, .cx16, .cx8, .evex512, .f16c, .fast_15bytenop, .fast_bextr, .fast_dpwssd, .fast_imm16, .fast_lzcnt, .fast_movbe, .fast_scalar_fsqrt, .fast_scalar_shift_masks, .fast_variable_perlane_shuffle, .fast_vector_fsqrt, .fma, .fsgsbase, .fsrm, .fxsr, .gfni, .idivq_to_divl, .invpcid, .lzcnt, .macrofusion, .mmx, .movbe, .mwaitx, .nopl, .pclmul, .pku, .popcnt, .prfchw, .rdpid, .rdpru, .rdrnd, .rdseed, .sahf, .sbb_dep_breaking, .sha, .shstk, .slow_shld, .smap, .smep, .sse, .sse2, .sse3, .sse4_1, .sse4_2, .sse4a, .ssse3, .vaes, .vpclmulqdq, .vzeroupper, .wbnoinvd, .x87, .xsave, .xsavec, .xsaveopt, .xsaves, }), }; pub const os: std.Target.Os = .{ .tag = .linux, .version_range = .{.linux = .{ .range = .{ .min = .{ .major = 6, .minor = 16, .patch = 0, }, .max = .{ .major = 6, .minor = 16, .patch = 0, }, }, .glibc = .{ .major = 2, .minor = 39, .patch = 0, }, .android = 29, }}, }; pub const target: std.Target = .{ .cpu = cpu, .os = os, .abi = abi, .ofmt = object_format, .dynamic_linker = .init("/nix/store/zdpby3l6azi78sl83cpad2qjpfj25aqx-glibc-2.40-66/lib/ld-linux-x86-64.so.2"), }; pub const object_format: std.Target.ObjectFormat = .elf; pub const mode: std.builtin.OptimizeMode = .Debug; pub const link_libc = false; pub const link_libcpp = false; pub const have_error_return_tracing = true; pub const valgrind_support = true; pub const sanitize_thread = false; pub const fuzz = false; pub const position_independent_code = false; pub const position_independent_executable = false; pub const strip_debug_info = false; pub const code_model: std.builtin.CodeModel = .default; pub const omit_frame_pointer = false; ``` -------------------------------- ### Zig Compile-Time Logging Example Source: https://ziglang.org/documentation/0.15.2 Demonstrates using @compileLog to print values during compilation. Note that @compileLog statements cause a compile error to prevent accidental inclusion in production code. ```zig const print = @import("std").debug.print; const num1 = blk: { var val1: i32 = 99; @compileLog("comptime val1 = ", val1); val1 = val1 + 1; break :blk val1; }; test "main" { @compileLog("comptime in main"); print("Runtime in main, num1 = {}.\n", .{num1}); } ``` -------------------------------- ### Zig Compile-Time Evaluation Example Source: https://ziglang.org/documentation/0.15.2 Demonstrates `comptime` variables and `inline` loops for partial compile-time evaluation. This code generates specialized functions based on `comptime` conditions. ```zig const expect = @import("std").testing.expect; const CmdFn = struct { name: []const u8, func: fn (i32) i32, }; const cmd_fns = [_]CmdFn{ CmdFn{ .name = "one", .func = one }, CmdFn{ .name = "two", .func = two }, CmdFn{ .name = "three", .func = three }, }; fn one(value: i32) i32 { return value + 1; } fn two(value: i32) i32 { return value + 2; } fn three(value: i32) i32 { return value + 3; } fn performFn(comptime prefix_char: u8, start_value: i32) i32 { var result: i32 = start_value; comptime var i = 0; inline while (i < cmd_fns.len) : (i += 1) { if (cmd_fns[i].name[0] == prefix_char) { result = cmd_fns[i].func(result); } } return result; } test "perform fn" { try expect(performFn('t', 1) == 6); try expect(performFn('o', 0) == 1); try expect(performFn('w', 99) == 99); } ``` -------------------------------- ### Zig Stack Trace Example Source: https://ziglang.org/documentation/0.15.2 Illustrates a traditional stack trace in Zig, which can be less informative for error propagation compared to error return traces. This code uses `@panic` to simulate a fatal error. ```zig pub fn main() void { foo(12); } fn foo(x: i32) void { if (x >= 5) { bar(); } else { bang2(); } } fn bar() void { if (baz()) { quux(); } else { hello(); } } fn baz() bool { return bang1(); } fn quux() void { bang2(); } fn hello() void { bang2(); } fn bang1() bool { return false; } fn bang2() void { @panic("PermissionDenied"); } ``` -------------------------------- ### Zig Slice Pointer Example Source: https://ziglang.org/documentation/0.15.2 Demonstrates slicing a mutable pointer to create a mutable slice and accessing elements. Slicing with comptime-known indexes produces another pointer to an array. ```zig const slice = ptr[start..end]; // The slice is mutable because we sliced a mutable pointer. try expect(@TypeOf(slice) == []u8); slice[2] = 3; try expect(array[2] == 3); // Again, slicing with comptime-known indexes will produce another pointer // to an array: const ptr2 = slice[2..3]; try expect(ptr2.len == 1); try expect(ptr2[0] == 3); try expect(@TypeOf(ptr2) == *[1]u8); ``` -------------------------------- ### Zig Error Return Trace Example Source: https://ziglang.org/documentation/0.15.2 Demonstrates how errors propagate through function calls using Zig's error return trace mechanism. This code is intended to be compiled and run to observe the error trace output. ```zig pub fn main() !void { try foo(12); } fn foo(x: i32) !void { if (x >= 5) { try bar(); } else { try bang2(); } } fn bar() !void { if (baz()) { try quux(); } else |err| switch (err) { error.FileNotFound => try hello(), } } fn baz() !void { try bang1(); } fn quux() !void { try bang2(); } fn hello() !void { try bang2(); } fn bang1() !void { return error.FileNotFound; } fn bang2() !void { return error.PermissionDenied; } ``` -------------------------------- ### Zig Print: Compile-Time Known Format String Source: https://ziglang.org/documentation/0.15.2 Shows how to use a compile-time known format string with the print function. This example ensures the format string and provided arguments are validated at compile time. ```zig const print = @import("std").debug.print; const a_number: i32 = 1234; const a_string = "foobar"; const fmt = "here is a string: '{s}' here is a number: {}\n"; pub fn main() void { print(fmt, .{ a_string, a_number }); } ``` ```shell $ `zig build-exe print_comptime-known_format.zig` $ `./print_comptime-known_format` here is a string: 'foobar' here is a number: 1234 ``` -------------------------------- ### Example of Compile-Time Branch Limit Exceeded Source: https://ziglang.org/documentation/0.15.2 This example demonstrates a compile-time error when the number of backwards branches exceeds the default limit of 1000. ```zig test "foo" { comptime { var i = 0; while (i < 1001) : (i += 1) {} } } ``` -------------------------------- ### Proof of concept print implementation Source: https://ziglang.org/documentation/0.15.2 A simplified implementation showing how format strings are parsed at comptime. ```zig const Writer = struct { /// Calls print and then flushes the buffer. pub fn print(self: *Writer, comptime format: []const u8, args: anytype) anyerror!void { const State = enum { start, open_brace, close_brace, }; comptime var start_index: usize = 0; comptime var state = State.start; comptime var next_arg: usize = 0; inline for (format, 0..) |c, i| { switch (state) { State.start => switch (c) { '{' => { if (start_index < i) try self.write(format[start_index..i]); state = State.open_brace; }, '}' => { if (start_index < i) try self.write(format[start_index..i]); state = State.close_brace; }, else => {}, }, State.open_brace => switch (c) { '{' => { state = State.start; start_index = i; }, '}' => { try self.printValue(args[next_arg]); next_arg += 1; state = State.start; start_index = i + 1; }, 's' => { continue; }, else => @compileError("Unknown format character: " ++ [1]u8{c}), }, State.close_brace => switch (c) { '}' => { state = State.start; start_index = i; }, else => @compileError("Single '}' encountered in format string"), }, } } comptime { if (args.len != next_arg) { @compileError("Unused arguments"); } if (state != State.start) { @compileError("Incomplete format string: " ++ format); } } if (start_index < format.len) { try self.write(format[start_index..format.len]); } try self.flush(); } fn write(self: *Writer, value: []const u8) !void { _ = self; _ = value; } pub fn printValue(self: *Writer, value: anytype) !void { _ = self; _ = value; } fn flush(self: *Writer) !void { _ = self; } }; ``` -------------------------------- ### Enum Export Error Example Source: https://ziglang.org/documentation/0.15.2 This example shows the error when trying to export a default enum type to C ABI without an explicit tag type. ```zig const Foo = enum { a, b, c }; export fn entry(foo: Foo) void { _ = foo; } ``` -------------------------------- ### Zig Build System for C Library and Executable Source: https://ziglang.org/documentation/0.15.2 Configures the Zig Build System to create a dynamic library from Zig code, compile a C source file, link them together, and create an executable. Includes running the executable as a test step. ```zig const std = @import("std"); pub fn build(b: *std.Build) void { const lib = b.addLibrary(.{ .linkage = .dynamic, .name = "mathtest", .root_module = b.createModule(.{ .root_source_file = b.path("mathtest.zig"), }), .version = .{ .major = 1, .minor = 0, .patch = 0 }, }); const exe = b.addExecutable(.{ .name = "test", .root_module = b.createModule(.{ .link_libc = true, }), }); exe.root_module.addCSourceFile(.{ .file = b.path("test.c"), .flags = &.{" -std=c99"} }); exe.root_module.linkLibrary(lib); b.default_step.dependOn(&exe.step); const run_cmd = exe.run(); const test_step = b.step("test", "Test the program"); test_step.dependOn(&run_cmd.step); } ``` -------------------------------- ### Address Of Source: https://ziglang.org/documentation/0.15.2 Gets the address of a value. ```zig &a ``` ```zig const x: u32 = 1234; const ptr = &x; ptr.* == 1234 ``` -------------------------------- ### Zig Array Initialization and Usage Source: https://ziglang.org/documentation/0.15.2 Demonstrates array literals, alternative initialization, size retrieval, string literals as arrays, iteration, modification, concatenation, repetition, zero initialization, and compile-time initialization using blocks and functions. ```zig const expect = @import("std").testing.expect; const assert = @import("std").debug.assert; const mem = @import("std").mem; // array literal const message = [_]u8{ 'h', 'e', 'l', 'l', 'o' }; // alternative initialization using result location const alt_message: [5]u8 = .{ 'h', 'e', 'l', 'l', 'o' }; comptime { assert(mem.eql(u8, &message, &alt_message)); } // get the size of an array comptime { assert(message.len == 5); } // A string literal is a single-item pointer to an array. const same_message = "hello"; comptime { assert(mem.eql(u8, &message, same_message)); } test "iterate over an array" { var sum: usize = 0; for (message) |byte| { sum += byte; } try expect(sum == 'h' + 'e' + 'l' * 2 + 'o'); } // modifiable array var some_integers: [100]i32 = undefined; test "modify an array" { for (&some_integers, 0..) |*item, i| { item.* = @intCast(i); } try expect(some_integers[10] == 10); try expect(some_integers[99] == 99); } // array concatenation works if the values are known // at compile time const part_one = [_]i32{ 1, 2, 3, 4 }; const part_two = [_]i32{ 5, 6, 7, 8 }; const all_of_it = part_one ++ part_two; comptime { assert(mem.eql(i32, &all_of_it, &[_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 })); } // remember that string literals are arrays const hello = "hello"; const world = "world"; const hello_world = hello ++ " " ++ world; comptime { assert(mem.eql(u8, hello_world, "hello world")); } // ** does repeating patterns const pattern = "ab" ** 3; comptime { assert(mem.eql(u8, pattern, "ababab")); } // initialize an array to zero const all_zero = [_]u16{0} ** 10; comptime { assert(all_zero.len == 10); assert(all_zero[5] == 0); } // use compile-time code to initialize an array var fancy_array = init: { var initial_value: [10]Point = undefined; for (&initial_value, 0..) |*pt, i| { pt.* = Point{ .x = @intCast(i), .y = @intCast(i * 2), }; } break :init initial_value; }; const Point = struct { x: i32, y: i32, }; test "compile-time array initialization" { try expect(fancy_array[4].x == 4); try expect(fancy_array[4].y == 8); } // call a function to initialize an array var more_points = [_]Point{makePoint(3)} ** 10; fn makePoint(x: i32) Point { return Point{ .x = x, .y = x * 2, }; } test "array initialization with function calls" { try expect(more_points[4].x == 3); try expect(more_points[4].y == 6); try expect(more_points.len == 10); } ``` -------------------------------- ### Using Inline Switch Prongs Source: https://ziglang.org/documentation/0.15.2 Demonstrates marking switch prongs as inline to analyze specific cases at comptime. ```zig const std = @import("std"); const expect = std.testing.expect; const expectError = std.testing.expectError; fn isFieldOptional(comptime T: type, field_index: usize) !bool { const fields = @typeInfo(T).@"struct".fields; return switch (field_index) { // This prong is analyzed twice with `idx` being a // comptime-known value each time. inline 0, 1 => |idx| @typeInfo(fields[idx].type) == .optional, else => return error.IndexOutOfBounds, }; } const Struct1 = struct { a: u32, b: ?u32 }; test "using @typeInfo with runtime values" { var index: usize = 0; try expect(!try isFieldOptional(Struct1, index)); index += 1; try expect(try isFieldOptional(Struct1, index)); index += 1; try expectError(error.IndexOutOfBounds, isFieldOptional(Struct1, index)); } // Calls to `isFieldOptional` on `Struct1` get unrolled to an equivalent // of this function: fn isFieldOptionalUnrolled(field_index: usize) !bool { return switch (field_index) { 0 => false, 1 => true, else => return error.IndexOutOfBounds, }; } ``` ```shell $ `zig test test_inline_switch.zig` 1/1 test_inline_switch.test.using @typeInfo with runtime values...OK All 1 tests passed. ``` -------------------------------- ### Verify Type Alignment Source: https://ziglang.org/documentation/0.15.2 Example usage of @alignOf to verify pointer alignment requirements. ```zig const assert = @import("std").debug.assert; comptime { assert(*u32 == *align(@alignOf(u32)) u32); } ``` -------------------------------- ### Zig Hello World Program Source: https://ziglang.org/documentation/0.15.2 A basic 'Hello, World!' program in Zig that writes to standard output. It requires importing the standard library and uses `std.fs.File.stdout().writeAll` for output. ```zig const std = @import("std"); pub fn main() !void { try std.fs.File.stdout().writeAll("Hello, World!\n"); } ``` -------------------------------- ### Render Zig Standard Library Documentation Source: https://ziglang.org/documentation/0.15.2 Use this command to render the Zig Standard Library documentation locally. ```shell zig std ``` -------------------------------- ### Building and Running C Executable with Zig Build System Source: https://ziglang.org/documentation/0.15.2 Command to build the project defined in the build.zig file, which includes compiling the Zig library, the C source, linking them, and running the resulting executable. ```shell $ `zig build test` 1379 ``` -------------------------------- ### Unattached Doc Comment Error Source: https://ziglang.org/documentation/0.15.2 Example of a compile error when a doc comment does not document anything. ```zig pub fn main() void {} /// End of file ``` ```shell $ `zig build-obj unattached_doc-comment.zig` /home/andy/dev/zig/doc/langref/unattached_doc-comment.zig:3:1: error: unattached documentation comment /// End of file ^~~~~~~~~~~~~~~ ``` -------------------------------- ### Get field offset with @offsetOf Source: https://ziglang.org/documentation/0.15.2 Returns the byte offset of a field relative to its containing struct. ```zig @offsetOf(comptime T: type, comptime field_name: []const u8) comptime_int ``` -------------------------------- ### Building a Static C Library with Zig Source: https://ziglang.org/documentation/0.15.2 Command to compile the Zig code into a static library that can be linked by C programs. ```shell $ `zig build-lib mathtest.zig` ``` -------------------------------- ### Zig Basic Slices Test Source: https://ziglang.org/documentation/0.15.2 Demonstrates the creation and properties of basic slices in Zig, including slicing arrays, alternative initialization, and the difference between slices and pointers to arrays. It also shows how bounds checking works and how to create empty slices. ```zig const expect = @import("std").testing.expect; const expectEqualSlices = @import("std").testing.expectEqualSlices; test "basic slices" { var array = [_]i32{ 1, 2, 3, 4 }; var known_at_runtime_zero: usize = 0; _ = &known_at_runtime_zero; const slice = array[known_at_runtime_zero..array.len]; // alternative initialization using result location const alt_slice: []const i32 = &.{ 1, 2, 3, 4 }; try expectEqualSlices(i32, slice, alt_slice); try expect(@TypeOf(slice) == []i32); try expect(&slice[0] == &array[0]); try expect(slice.len == array.len); // If you slice with comptime-known start and end positions, the result is // a pointer to an array, rather than a slice. const array_ptr = array[0..array.len]; try expect(@TypeOf(array_ptr) == *[array.len]i32); // You can perform a slice-by-length by slicing twice. This allows the compiler // to perform some optimisations like recognising a comptime-known length when // the start position is only known at runtime. var runtime_start: usize = 1; _ = &runtime_start; const length = 2; const array_ptr_len = array[runtime_start..][0..length]; try expect(@TypeOf(array_ptr_len) == *[length]i32); // Using the address-of operator on a slice gives a single-item pointer. try expect(@TypeOf(&slice[0]) == *i32); // Using the `ptr` field gives a many-item pointer. try expect(@TypeOf(slice.ptr) == [*]i32); try expect(@intFromPtr(slice.ptr) == @intFromPtr(&slice[0])); // Slices have array bounds checking. If you try to access something out // of bounds, you'll get a safety check failure: slice[10] += 1; // Note that `slice.ptr` does not invoke safety checking, while `&slice[0]` // asserts that the slice has len > 0. // Empty slices can be created like this: const empty1 = &[0]u8{}; // If the type is known you can use this short hand: const empty2: []u8 = &.{}; try expect(empty1.len == 0); try expect(empty2.len == 0); // A zero-length initialization can always be used to create an empty slice, even if the slice is mutable. // This is because the pointed-to data is zero bits long, so its immutability is irrelevant. } ``` ```shell $ `zig test test_basic_slices.zig` 1/1 test_basic_slices.test.basic slices...thread 2902466 panic: index out of bounds: index 10, len 4 /home/andy/dev/zig/doc/langref/test_basic_slices.zig:41:10: 0x102e3c0 in test.basic slices (test_basic_slices.zig) slice[10] += 1; ^ /home/andy/dev/zig/lib/compiler/test_runner.zig:218:25: 0x1160b60 in mainTerminal (test_runner.zig) if (test_fn.func()) |_| { ^ /home/andy/dev/zig/lib/compiler/test_runner.zig:66:28: 0x1159d81 in main (test_runner.zig) return mainTerminal(); ^ /home/andy/dev/zig/lib/std/start.zig:618:22: 0x1153b1d in posixCallMainAndExit (std.zig) root.main(); ^ /home/andy/dev/zig/lib/std/start.zig:232:5: 0x11533b1 in _start (std.zig) asm volatile (switch (native_arch) { ^ ???:?:?: 0x0 in ??? (???) error: the following test command crashed: /home/andy/dev/zig/.zig-cache/o/0e584e3dac6333a0b2d5158992704660/test --seed=0x665d12a2 ``` -------------------------------- ### Invalid Runtime Comptime Argument Source: https://ziglang.org/documentation/0.15.2 Example of a compile error when passing a runtime-known value to a comptime parameter. ```zig fn max(comptime T: type, a: T, b: T) T { return if (a > b) a else b; } test "try to pass a runtime type" { foo(false); } fn foo(condition: bool) void { const result = max(if (condition) f32 else u64, 1234, 5678); _ = result; } ``` ```shell $ zig test test_unresolved_comptime_value.zig /home/andy/dev/zig/doc/langref/test_unresolved_comptime_value.zig:8:28: error: unable to resolve comptime value const result = max(if (condition) f32 else u64, 1234, 5678); ^~~~~~~~~ /home/andy/dev/zig/doc/langref/test_unresolved_comptime_value.zig:8:24: note: argument to comptime parameter must be comptime-known const result = max(if (condition) f32 else u64, 1234, 5678); ^~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/andy/dev/zig/doc/langref/test_unresolved_comptime_value.zig:1:8: note: parameter declared comptime here fn max(comptime T: type, a: T, b: T) T { ^~~~~~~~ referenced by: test.try to pass a runtime type: /home/andy/dev/zig/doc/langref/test_unresolved_comptime_value.zig:5:8 ``` -------------------------------- ### Getting Field Type with @FieldType Source: https://ziglang.org/documentation/0.15.2 Returns the type of a field given the container type and the field name. ```zig @FieldType(comptime Type: type, comptime field_name: []const u8) type ``` -------------------------------- ### Standard Build Options Configuration Source: https://ziglang.org/documentation/0.15.2 Configures standard optimization options in a build.zig file. ```zig const std = @import("std"); pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const exe = b.addExecutable(.{ .name = "example", .root_module = b.createModule(.{ .root_source_file = b.path("example.zig"), .optimize = optimize, }), }); b.default_step.dependOn(&exe.step); } ```