Arrays

arrays.zig

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

See also: