Arrays

arrays.zig

  1. const expect = @import("std").testing.expect;
  2. const assert = @import("std").debug.assert;
  3. const mem = @import("std").mem;
  4. // array literal
  5. const message = [_]u8{ 'h', 'e', 'l', 'l', 'o' };
  6. // get the size of an array
  7. comptime {
  8. assert(message.len == 5);
  9. }
  10. // A string literal is a single-item pointer to an array literal.
  11. const same_message = "hello";
  12. comptime {
  13. assert(mem.eql(u8, &message, same_message));
  14. }
  15. test "iterate over an array" {
  16. var sum: usize = 0;
  17. for (message) |byte| {
  18. sum += byte;
  19. }
  20. try expect(sum == 'h' + 'e' + 'l' * 2 + 'o');
  21. }
  22. // modifiable array
  23. var some_integers: [100]i32 = undefined;
  24. test "modify an array" {
  25. for (some_integers) |*item, i| {
  26. item.* = @intCast(i32, i);
  27. }
  28. try expect(some_integers[10] == 10);
  29. try expect(some_integers[99] == 99);
  30. }
  31. // array concatenation works if the values are known
  32. // at compile time
  33. const part_one = [_]i32{ 1, 2, 3, 4 };
  34. const part_two = [_]i32{ 5, 6, 7, 8 };
  35. const all_of_it = part_one ++ part_two;
  36. comptime {
  37. assert(mem.eql(i32, &all_of_it, &[_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }));
  38. }
  39. // remember that string literals are arrays
  40. const hello = "hello";
  41. const world = "world";
  42. const hello_world = hello ++ " " ++ world;
  43. comptime {
  44. assert(mem.eql(u8, hello_world, "hello world"));
  45. }
  46. // ** does repeating patterns
  47. const pattern = "ab" ** 3;
  48. comptime {
  49. assert(mem.eql(u8, pattern, "ababab"));
  50. }
  51. // initialize an array to zero
  52. const all_zero = [_]u16{0} ** 10;
  53. comptime {
  54. assert(all_zero.len == 10);
  55. assert(all_zero[5] == 0);
  56. }
  57. // use compile-time code to initialize an array
  58. var fancy_array = init: {
  59. var initial_value: [10]Point = undefined;
  60. for (initial_value) |*pt, i| {
  61. pt.* = Point{
  62. .x = @intCast(i32, i),
  63. .y = @intCast(i32, i) * 2,
  64. };
  65. }
  66. break :init initial_value;
  67. };
  68. const Point = struct {
  69. x: i32,
  70. y: i32,
  71. };
  72. test "compile-time array initialization" {
  73. try expect(fancy_array[4].x == 4);
  74. try expect(fancy_array[4].y == 8);
  75. }
  76. // call a function to initialize an array
  77. var more_points = [_]Point{makePoint(3)} ** 10;
  78. fn makePoint(x: i32) Point {
  79. return Point{
  80. .x = x,
  81. .y = x * 2,
  82. };
  83. }
  84. test "array initialization with function calls" {
  85. try expect(more_points[4].x == 3);
  86. try expect(more_points[4].y == 6);
  87. try expect(more_points.len == 10);
  88. }
  1. $ zig test arrays.zig
  2. Test [1/4] test "iterate over an array"...
  3. Test [2/4] test "modify an array"...
  4. Test [3/4] test "compile-time array initialization"...
  5. Test [4/4] test "array initialization with function calls"...
  6. All 4 tests passed.

See also:

Anonymous List Literals

Similar to Enum Literals and Anonymous Struct Literals the type can be omitted from array literals:

anon_list.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  3. test "anonymous list literal syntax" {
  4. var array: [4]u8 = .{11, 22, 33, 44};
  5. try expect(array[0] == 11);
  6. try expect(array[1] == 22);
  7. try expect(array[2] == 33);
  8. try expect(array[3] == 44);
  9. }
  1. $ zig test anon_list.zig
  2. Test [1/1] test "anonymous list literal syntax"...
  3. All 1 tests passed.

If there is no type in the result location then an anonymous list literal actually turns into a struct with numbered field names:

infer_list_literal.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  3. test "fully anonymous list literal" {
  4. try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"});
  5. }
  6. fn dump(args: anytype) !void {
  7. try expect(args.@"0" == 1234);
  8. try expect(args.@"1" == 12.34);
  9. try expect(args.@"2");
  10. try expect(args.@"3"[0] == 'h');
  11. try expect(args.@"3"[1] == 'i');
  12. }
  1. $ zig test infer_list_literal.zig
  2. Test [1/1] test "fully anonymous list literal"...
  3. All 1 tests passed.

Multidimensional Arrays

Mutlidimensional arrays can be created by nesting arrays:

multidimensional.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  3. const mat4x4 = [4][4]f32{
  4. [_]f32{ 1.0, 0.0, 0.0, 0.0 },
  5. [_]f32{ 0.0, 1.0, 0.0, 1.0 },
  6. [_]f32{ 0.0, 0.0, 1.0, 0.0 },
  7. [_]f32{ 0.0, 0.0, 0.0, 1.0 },
  8. };
  9. test "multidimensional arrays" {
  10. // Access the 2D array by indexing the outer array, and then the inner array.
  11. try expect(mat4x4[1][1] == 1.0);
  12. // Here we iterate with for loops.
  13. for (mat4x4) |row, row_index| {
  14. for (row) |cell, column_index| {
  15. if (row_index == column_index) {
  16. try expect(cell == 1.0);
  17. }
  18. }
  19. }
  20. }
  1. $ zig test multidimensional.zig
  2. Test [1/1] test "multidimensional arrays"...
  3. All 1 tests passed.

Sentinel-Terminated Arrays

The syntax [N:x]T describes an array which has a sentinel element of value x at the index corresponding to len.

null_terminated_array.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  3. test "null terminated array" {
  4. const array = [_:0]u8 {1, 2, 3, 4};
  5. try expect(@TypeOf(array) == [4:0]u8);
  6. try expect(array.len == 4);
  7. try expect(array[4] == 0);
  8. }
  1. $ zig test null_terminated_array.zig
  2. Test [1/1] test "null terminated array"...
  3. All 1 tests passed.

See also: