Slices

    Shell

    1. 1/1 test "basic slices"... thread 792342 panic: index out of bounds
    2. /home/andy/Downloads/zig/docgen_tmp/test.zig:22:10: 0x207c83 in test "basic slices" (test)
    3. slice[10] += 1;
    4. ^
    5. /home/andy/Downloads/zig/lib/std/special/test_runner.zig:80:28: 0x22f6d3 in std.special.main (test)
    6. } else test_fn.func();
    7. ^
    8. /home/andy/Downloads/zig/lib/std/start.zig:543:22: 0x2280cc in std.start.callMain (test)
    9. root.main();
    10. ^
    11. /home/andy/Downloads/zig/lib/std/start.zig:495:12: 0x20953e in std.start.callMainWithArgs (test)
    12. return @call(.{ .modifier = .always_inline }, callMain, .{});
    13. ^
    14. /home/andy/Downloads/zig/lib/std/start.zig:409:17: 0x2085d6 in std.start.posixCallMainAndExit (test)
    15. std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
    16. ^
    17. /home/andy/Downloads/zig/lib/std/start.zig:322:5: 0x2083e2 in std.start._start (test)
    18. @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
    19. ^
    20. error: the following test command crashed:
    21. docgen_tmp/zig-cache/o/8e4964e05ddaf866e77360a551b3c05b/test /home/andy/Downloads/zig/build-release/zig

    This is one reason we prefer slices to pointers.

    slices.zig

    1. const std = @import("std");
    2. const expect = std.testing.expect;
    3. const mem = std.mem;
    4. const fmt = std.fmt;
    5. test "using slices for strings" {
    6. // Zig has no concept of strings. String literals are const pointers
    7. // to null-terminated arrays of u8, and by convention parameters
    8. // that are "strings" are expected to be UTF-8 encoded slices of u8.
    9. // Here we coerce *const [5:0]u8 and *const [6:0]u8 to []const u8
    10. var all_together: [100]u8 = undefined;
    11. // You can use slice syntax on an array to convert an array into a slice.
    12. const all_together_slice = all_together[0..];
    13. // String concatenation example.
    14. const hello_world = try fmt.bufPrint(all_together_slice, "{s} {s}", .{ hello, world });
    15. // Generally, you can use UTF-8 and not worry about whether something is a
    16. // string. If you don't need to deal with individual characters, no need
    17. // to decode.
    18. try expect(mem.eql(u8, hello_world, "hello 世界"));
    19. }
    20. test "slice pointer" {
    21. var array: [10]u8 = undefined;
    22. const ptr = &array;
    23. // You can use slicing syntax to convert a pointer into a slice:
    24. const slice = ptr[0..5];
    25. slice[2] = 3;
    26. try expect(slice[2] == 3);
    27. // The slice is mutable because we sliced a mutable pointer.
    28. // Furthermore, it is actually a pointer to an array, since the start
    29. // and end indexes were both comptime-known.
    30. try expect(@TypeOf(slice) == *[5]u8);
    31. // You can also slice a slice:
    32. const slice2 = slice[2..3];
    33. try expect(slice2.len == 1);
    34. try expect(slice2[0] == 3);
    35. }

    Shell

    The syntax [:x]T is a slice which has a runtime known length and also guarantees a sentinel value at the element indexed by the length. The type does not guarantee that there are no sentinel elements before that. Sentinel-terminated slices allow element access to the index.

    null_terminated_slice.zig

    1. const std = @import("std");
    2. const expect = std.testing.expect;
    3. test "null terminated slice" {
    4. const slice: [:0]const u8 = "hello";
    5. try expect(slice.len == 5);
    6. try expect(slice[5] == 0);
    7. }

    Shell

    1. $ zig test null_terminated_slice.zig
    2. 1/1 test "null terminated slice"... OK
    3. All 1 tests passed.

    Sentinel-terminated slices can also be created using a variation of the slice syntax data[start..end :x], where data is a many-item pointer, array or slice and x is the sentinel value.

    Shell

    1. $ zig test null_terminated_slicing.zig
    2. 1/1 test "null terminated slicing"... OK
    3. All 1 tests passed.

    Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is actually the sentinel value. If this is not the case, safety-protected results.

    test.zig

    1. const std = @import("std");
    2. const expect = std.testing.expect;
    3. test "sentinel mismatch" {
    4. var array = [_]u8{ 3, 2, 1, 0 };
    5. // Creating a sentinel-terminated slice from the array with a length of 2
    6. // will result in the value `1` occupying the sentinel element position.
    7. // This does not match the indicated sentinel value of `0` and will lead
    8. // to a runtime panic.
    9. var runtime_length: usize = 2;
    10. const slice = array[0..runtime_length :0];
    11. _ = slice;

    Shell