Pointer increment

In 1 or 2 cases I have to use pointer arithmic for structs in an array.
Is this the right / fastest way to do that?

pub fn ptr_add(T: type, ptr: *const T, comptime delta: comptime_int) *T {
    return @ptrFromInt(@intFromPtr(ptr) + @sizeOf(T) * delta);
}

pub fn ptr_sub(T: type, ptr: *const T, comptime delta: comptime_int) *T {
    return @ptrFromInt(@intFromPtr(ptr) - @sizeOf(T) * delta);
}
1 Like

can’t the pointer be a many pointer instead?

3 Likes

You’re doing an implicit @constCast here which can quite easily lead to a crash if you’re not careful.

Apart from that, as @hachanuy has already said the ‘Zig way’ to do this would be many-item pointers (which support pointer arithmetic directly).
You’d currently need two @ptrCasts for that though (assuming ptr has to be a single pointer), so it’s not necessarily more concise. Relevant proposal:

2 Likes

To expand on this, [*]T multi-item pointers support pointer arithmetic since at least a few minor language versions back:

var a: [*]T = &array[i];
var b: [*]T = a + delta;

But you should ask yourself why you believe pointer arithmetic is the answer to your problem in the first place. Using arrays/slices and indices is safer because you get bounds checking for free, and in the vast majority of cases any difference between accessing by index and incrementing a pointer will be negligible. It’s foolish to micro-optimize without numbers backing your decision.

The problem with a many item pointer is we always need to access it with ptr[0], which I find inconvenient. I use that variable a lot.

Safety is not important. Speed is. It is a chessprogram.

fn search(node: *Node) {
    const childnode: *Node = ptr_add(node, 1);
    const previous_with_same_side_to_move: *Node = ptr_sub(node, 2);
}

I could of course pass the index of the node but then I have to create a variable:

fn search(node_idx: usize) {
    const node: *Node = nodes[node_idx];
}

Passing node is more readable I think. But the pointer add sub stuff is inconvenient.

Zig prioritizes readabilty over writability. To a reader, *T communicates that there is only one T, while [*]T communicates that there are multiple Ts. If you start treating *T like an array of Ts you are not communicating your intent effectively and your reader (which could be you yourself a few months from now) will be confused.

I would still encourage you to collect some actual perf numbers before you write your code in an overtly obscur way. You need to verify your assumptions against hard facts because your initial hunches may be very wrong. For example, an optimizing compiler might quickly recognize array indexing and vectorize your code, but won’t recognize pointer incrementation and will leave your code unoptimized.

4 Likes

I will contemplate yes. i don’t like the ptr stuff.
i will either use an index either use a multi ptr.

you have to do ptr.* if you incorrectly use a single item pointer anyway, how is ptr[0] any worse.