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:
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.
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.