# Slices

test.zig

constassert=@import("std").debug.assert;test "basic slices"{var array =[_]i32{1,2,3,4};// A slice is a pointer and a length. The difference between an array and// a slice is that the array's length is part of the type and known at// compile-time, whereas the slice's length is known at runtime.// Both can be accessed with the len field.var known_at_runtime_zero: usize =0;const slice = array[known_at_runtime_zero..array.len];assert(&slice[0]==&array[0]);assert(slice.len == array.len);// Using the address-of operator on a slice gives a pointer to a single// item, while using the ptr field gives an unknown length pointer.assert(@TypeOf(slice.ptr)==[*]i32);assert(@TypeOf(&slice[0])==*i32);assert(@ptrToInt(slice.ptr)==@ptrToInt(&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 >= 1.}
$zig test test.zig1/1 test "basic slices"...index out of bounds/deps/zig/docgen_tmp/test.zig:22:10:0x204cc6in test "basic slices"(test) slice[10]+=1;^/deps/zig/lib/std/special/test_runner.zig:47:28:0x22bc1ein std.special.main (test)}else test_fn.func();^/deps/zig/lib/std/start.zig:253:37:0x20574din std.start.posixCallMainAndExit (test)const result = root.main()catch|err|{^/deps/zig/lib/std/start.zig:123:5:0x20548fin std.start._start (test)@call(.{.modifier =.never_inline }, posixCallMainAndExit,.{});^Tests failed.Use the following command to reproduce the failure:/deps/zig/docgen_tmp/test This is one reason we prefer slices to pointers. slices.zig const std =@import("std");constassert= std.debug.assert;const mem = std.mem;const fmt = std.fmt;test "using slices for strings"{// Zig has no concept of strings. String literals are const pointers to// arrays of u8, and by convention parameters that are "strings" are// expected to be UTF-8 encoded slices of u8.// Here we coerce [5]u8 to []const u8const hello:[]const u8 ="hello";const world:[]const u8 ="世界";var all_together:[100]u8 =undefined;// You can use slice syntax on an array to convert an array into a slice.const all_together_slice = all_together[0..];// String concatenation example.const hello_world =try fmt.bufPrint(all_together_slice,"{} {}",.{ hello, world });// Generally, you can use UTF-8 and not worry about whether something is a// string. If you don't need to deal with individual characters, no need// to decode.assert(mem.eql(u8, hello_world,"hello 世界"));}test "slice pointer"{var array:[10]u8 =undefined;const ptr =&array;// You can use slicing syntax to convert a pointer into a slice:const slice = ptr[0..5]; slice[2]=3;assert(slice[2]==3);// The slice is mutable because we sliced a mutable pointer.// Furthermore, it is actually a pointer to an array, since the start// and end indexes were both comptime-known.assert(@TypeOf(slice)==*[5]u8);// You can also slice a slice:const slice2 = slice[2..3];assert(slice2.len ==1);assert(slice2[0]==3);} $ zig test slices.zig1/2 test "using slices for strings"...OK2/2 test "slice pointer"...OKAll2 tests passed.

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 len index.
const std =@import("std");constassert= std.debug.assert;test "null terminated slice"{const slice:[:0]const u8 ="hello";assert(slice.len ==5);assert(slice[5]==0);}
\$ zig test null_terminated_slice.zig1/1 test "null terminated slice"...OKAll1 tests passed.