Slices

test.zig

  1. const assert = @import("std").debug.assert;
  2. test "basic slices" {
  3. var array = []i32{ 1, 2, 3, 4 };
  4. // A slice is a pointer and a length. The difference between an array and
  5. // a slice is that the array's length is part of the type and known at
  6. // compile-time, whereas the slice's length is known at runtime.
  7. // Both can be accessed with the `len` field.
  8. const slice = array[0..array.len];
  9. assert(&slice[0] == &array[0]);
  10. assert(slice.len == array.len);
  11. // Using the address-of operator on a slice gives a pointer to a single
  12. // item, while using the `ptr` field gives an unknown length pointer.
  13. assert(@typeOf(slice.ptr) == [*]i32);
  14. assert(@typeOf(&slice[0]) == *i32);
  15. assert(@ptrToInt(slice.ptr) == @ptrToInt(&slice[0]));
  16. // Slices have array bounds checking. If you try to access something out
  17. // of bounds, you'll get a safety check failure:
  18. slice[10] += 1;
  19. // Note that `slice.ptr` does not invoke safety checking, while `&slice[0]`
  20. // asserts that the slice has len >= 1.
  21. }
  1. $ zig test test.zig
  2. Test 1/1 basic slices...index out of bounds
  3. /home/andy/dev/zig/docgen_tmp/test.zig:21:10: 0x2041e5 in ??? (test)
  4. slice[10] += 1;
  5. ^
  6. /home/andy/dev/zig/build/lib/zig/std/special/test_runner.zig:13:25: 0x225d0b in ??? (test)
  7. if (test_fn.func()) |_| {
  8. ^
  9. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:122:22: 0x225496 in ??? (test)
  10. root.main() catch |err| {
  11. ^
  12. /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:43:5: 0x225201 in ??? (test)
  13. @noInlineCall(posixCallMainAndExit);
  14. ^
  15. Tests failed. Use the following command to reproduce the failure:
  16. /home/andy/dev/zig/docgen_tmp/test

This is one reason we prefer slices to pointers.

slices.zig

  1. const assert = @import("std").debug.assert;
  2. const mem = @import("std").mem;
  3. const fmt = @import("std").fmt;
  4. test "using slices for strings" {
  5. // Zig has no concept of strings. String literals are arrays of u8, and
  6. // in general the string type is []u8 (slice of u8).
  7. // Here we implicitly cast [5]u8 to []const u8
  8. const hello: []const u8 = "hello";
  9. const world: []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, "{} {}", 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. assert(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. assert(slice[2] == 3);
  27. // The slice is mutable because we sliced a mutable pointer.
  28. assert(@typeOf(slice) == []u8);
  29. // You can also slice a slice:
  30. const slice2 = slice[2..3];
  31. assert(slice2.len == 1);
  32. assert(slice2[0] == 3);
  33. }
  34. test "slice widening" {
  35. // Zig supports slice widening and slice narrowing. Cast a slice of u8
  36. // to a slice of anything else, and Zig will perform the length conversion.
  37. const array align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
  38. const slice = @bytesToSlice(u32, array[0..]);
  39. assert(slice.len == 2);
  40. assert(slice[0] == 0x12121212);
  41. assert(slice[1] == 0x13131313);
  42. }
  1. $ zig test slices.zig
  2. Test 1/3 using slices for strings...OK
  3. Test 2/3 slice pointer...OK
  4. Test 3/3 slice widening...OK
  5. All tests passed.

See also: