When is it useful to take the address of a parameter in Zig?

In a recent help thread, it came up that there can be some odd behavior when taking the address of a parameter in Zig. Since function parameters in Zig are immutable, I have the following question:

What is a situation where it is useful to take the address of a parameter in Zig?

1 Like

In the case that a big parameter passed “by value” is compiled to be passed by const reference via parameter reference optimization, I thought that maybe taking a reference to the parameter would avoid making a copy to pass it along to a further function that takes a const reference.

const S = extern struct {
    nums: [2048]u64,
};

fn byVal(s: S) u64 {
    return byRef(&s);
}

fn byRef(s: *const S) u64 {
    var sum: u64 = 0;
    for (s.nums) |n| {
        sum += n;
    }
    return sum;
}

But as far as I can tell, it seems that currently a local copy is made whenever a reference is observed. Perhaps this is a bug or is intended to be optimized in the future?

In debug mode, values are always passed by values. Did you try it with optimizations enabled?

I was examining behavior and produced assembly using ReleaseFast and ReleaseSmall.

Relevant issue on github: Pass by reference "optimization" copies the entire struct on the stack when taking its address. (this didn't happen in stage1) · Issue #16343 · ziglang/zig · GitHub

2 Likes