# Runtime Array creation

**URL:** <https://ziggit.dev/t/runtime-array-creation/16691>\
**Category:** Explain\
**Tags:** language, memory-management, standard-library\
**Created:** [July 13, 2026, 3:52pm UTC](https://ziggit.dev/t/runtime-array-creation/16691 "2026-07-13T15:52:27Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![plano](https://ziggit.dev/user_avatar/ziggit.dev/plano/32/3730_2.png) [@plano](https://ziggit.dev/u/plano)\
**Post date:** [July 13, 2026, 3:52pm UTC](https://ziggit.dev/t/runtime-array-creation/16691/1 "2026-07-13T15:52:27Z")

</div>

Hi, recently ive been having to create runtime arrays where i have some data to iterate over and append it to an array, and although i have a way that works (and even think is the proper/accepted way)

One of my usecases: create an array of the cli arguments. Solution:

```zig
pub fn argsToArray(gpa: std.mem.Allocator, args: std.process.Args) []const []const u8 {
    var result: std.ArrayList([]const u8) = .empty;
    defer result.deinit(gpa);

    var iter = args.iterate();
    _ = iter.skip(); // skip program name
    while (iter.next()) |arg| result.append(gpa, arg) catch @panic("insufficient memory");
    return result.toOwnedSlice(gpa) catch @panic("insufficient memory");
}

```

I dont like having to use ArrayList. i dont quite like it. I think i find it “ugly”. And i feel it has unnecessary allocations. And i feel im having to create a lot of ArrayList in so many different places (even more so when there are ArrayList inside something that im also grouping in ArrayList).

### TL;DR

This pattern appears again and again and again. And i dont quite actually like it and am wondering if theres another simpler way im missing, or even if not simpler, prettier.

#### Extra question:

- why does `args.Iterator` not have a `peek()`?
- whats more recommended: returning `toOwnedSlice()` or keeping the `ArrayList` around?

## The extra info:

### (All of this is not really relevant to the question)

The reason i had to do that instead of using `args.Iterator` I needed to parse the cli where some option would take a list of arguments `--foo a b c --bar`.

```zig
while (iter.next()) |opt| {
  if (eql(u8, opt, "--foo")) {
    while (iter.next()) |arg| {
      if (startswith(arg, '-') break;
      ...
    }
  } else if (eql(u8, opt, "--bar") {...}
}

```

This is simple, and clean, and gets the values fine, but then `--bar` gets skipped because we already looked at it with `next()`. (and im realising i could have the `else if` be an `if` and it would get executed next, but that gets messy with more options and other complex parsings)

So we would need the `args.Iterator` to either be able to set the index back, which not possible because the iterator is consuming the arguments and only keeps `remaining`, or for the iterator to have a `peek` which it doesnt have (and i cant understand why it wouldnt, so thats another question if anyone can answer). So instead i had to do what i pasted up there: go throug it all and create my own array with all the elements. And then have my own iterator that has an index so each `next` increments the index and then i can `if (startswith(arg, '-') {iter.index -=1; break;}`.

### More cases where i had to do this:

Right here, getting the list of options passed to `--foo`.  
When i was using the `args.Iterator` i would need to do it with an ArrayList again.  
Not anymore though. Now using my iterator that keeps the og array i can get the iter index when we enter the `--foo` and get the index when we get the next option that starts with `-` and return a slice/copy of the slice (copy of slice if i deallocate the args list after parsing, slice otherwise; havent decided yet what to do, for now i copy).  
Im quite happy with this 😃

(Actually `--foo` takes multiple lists so `--foo a b --bar --foo c` would set `foo=[[a,b],[c]]`), so thats another ArrayList)

Im working with sqlite data. The sqlite statement gives me an iterator. So i want to iter through the rows to get an array and then i will further work with that.  
Same process.

And lastly (so far) those rows have some data in strings that i want to split into an array of strings.  
`mem.split...` returns an iterator. Again the same.  
Although im thinking that for this particular case i could do a `mem.count` of the splitting character and then use an `ArrayList with a fixedbuffer of that lenght. And that should remove some allocations.

---

<div class="post-metadata">

**Author:** ![alanza](https://ziggit.dev/user_avatar/ziggit.dev/alanza/32/6006_2.png) [@alanza](https://ziggit.dev/u/alanza)\
**Post date:** [July 13, 2026, 3:58pm UTC](https://ziggit.dev/t/runtime-array-creation/16691/2 "2026-07-13T15:58:49Z")

</div>

I’m sorry, I didn’t understand at all what this post is looking for.

For the case of args specifically, if you want a more flexible form of iteration, you might want to do `args.toSlice(gpa)` and then work with the resulting `[]const [:0]const u8`.

If you want to avoid `ArrayList` because of too many allocations you could try the [Reserve First](https://matklad.github.io/2025/08/16/reserve-first.html) strategy? or rethink your memory layout to be flatter? (struct-of-arrays style thinking)

---

<div class="post-metadata">

**Author:** ![plano](https://ziggit.dev/user_avatar/ziggit.dev/plano/32/3730_2.png) [@plano](https://ziggit.dev/u/plano)\
**Post date:** [July 13, 2026, 4:19pm UTC](https://ziggit.dev/t/runtime-array-creation/16691/4 "2026-07-13T16:19:56Z")

</div>

> [@alanza](#):
>
> I’m sorry, I didn’t understand at all what this post is looking for.

its true, this post is very messy. tried to gather the important thoughts/questions in the tldr, which is “what are some other options for this pattern that yield the same result, an array at runtime”.

but i gotta say that even for not understanding your answer was quite helpful 😃

> [@alanza](#):
>
> `args.toSlice(gpa)`

how even did i miss this when looking at std lol

> [@alanza](#):
>
> rethink your memory layout to be flatter? (struct-of-arrays style thinking)

could you expand on this? maybe some example?

---

<div class="post-metadata">

**Author:** ![alanza](https://ziggit.dev/user_avatar/ziggit.dev/alanza/32/6006_2.png) [@alanza](https://ziggit.dev/u/alanza)\
**Post date:** [July 13, 2026, 4:58pm UTC](https://ziggit.dev/t/runtime-array-creation/16691/5 "2026-07-13T16:58:37Z")

</div>

Sure! the “struct-of-arrays” thinking is inspired by things like `std.MultiArrayList`, “data-oriented design” etc. in case keywords are useful.

Here’s how I’ve used it in a project that implements the VDB data structure. For a quick and shallow introduction, you could skim through the “deep” dive here: [JangaFX - Insight: VDB, a deep dive](https://jangafx.com/insights/vdb-a-deep-dive)

The main thing to take away is that a VDB is a bit like a B-tree or an octree; nodes are nested inside nodes and they have physical coordinates. The Zig project I’m about to link to below used to, like the (very naïve) Odin code in the link above, also model the tree as a tree in memory, so that each Node object would maintain its own `std.AutoHashMap` of children.

The problem with this is of course that it is extremely wasteful in terms of memory and cache locality, since each node has a separate allocation for its children.

Here is how the Zig project currently structures the VDB type in memory:

> <https://github.com/joachimbbp/neurovolume/blob/74af8f37ea77a80540b7a6e479e709ec0e3d31b6/src/zig/vdb543.zig#L239-L262>

This is a classic “struct of arrays”: all of the nodes at the possible heights “A”, “B” and “C” are stored contiguously in memory by type reducing the number of individual allocations a VDB manages from `O(n^3)` to `O(1)`.

This of course makes traversing the tree in memory slightly more complicated; I use a technique detailed in the [original white paper](https://www.museth.org/Ken/Publications_files/Museth_TOG13.pdf).

In testing my reorganization, my results saw a ~25% speedup and reduced peak rss by a factor of 3, so there are real gains to be made 🙂

---

<div class="post-metadata">

**Author:** ![vulpesx](https://ziggit.dev/user_avatar/ziggit.dev/vulpesx/32/3989_2.png) [@vulpesx](https://ziggit.dev/u/vulpesx)\
**Post date:** [July 14, 2026, 3:13am UTC](https://ziggit.dev/t/runtime-array-creation/16691/6 "2026-07-14T03:13:28Z")

</div>

> [@alanza](#):
>
> do `args.toSlice(gpa)`

`toSlice` expects an arena as it leaks memory.
