Moreover, in C usual notation a[i] is also syntactic sugar.
Non-sugar form for accessing elements of an array is
float *a;
int i;
... *(a + i)...
Which means
take the address of the beginning of the array (a)
add i * sizeof(float) to it → this is the address of i-th element of the array
dereference address obtained
And since a + 4 * i = 4 * i + a, you can write wierdly looking things like i[a] instead of a[i], if I am not mistaken.
Anyway, to get an address of an i-th element of an array you do a + i * sizeof(ArrayElement),
this is why indexing usually starts with zero, but not one (yes, Pascal is one of the exceptions).
However, for multidimensional arrays [] notation is not merely syntactic sugar. It does simplify the presentation of array element significantly.
Otherwise you could argue that everything is syntactic sugar - for loops, switch’es, etc.
I was referring to this specifically - you can start indexing with whatever you want:
program exArrays;
var
n: array [-10..10] of integer; (* n is an array of 21 integers *)
i, j: integer;
begin
(* initialize elements of array n *)
for i := -10 to 10 do
n[ i ] := i * 2;
(* output each array element's value *)
for j:= -10 to 10 do
writeln('Element[', j, '] = ', n[j] );
end.
However, you can achieve the same result like this:
program exArrays;
var
n: array [0..20] of integer; (* n is an array of 21 integers *)
i, j: integer;
begin
(* initialize elements of array n *)
for i := 0 to 20 do
n[ i ] := (i - 10) * 2;
(* output each array element's value *)
for j:= 0 to 20 do
writeln('Element[', j - 10, '] = ', n[j] );
end.
Ideone link.
Moreover, I’m pretty sure this is how the first program works “under the hood” as well, hence my question - why is this important to OP.
Yes, it’s the default language for highlighting if you don’t specify one or if you add zig after the backticks. I don’t think Discourse can handle Pascal, but I’ll check to make sure.
I have a good experience with one-based array index in Julia. It was so straightforward. You can’t make unnecessary mistakes when manipulating strings and arrays using such indexes.
I have also used Julia in the past and honestly I found it pretty annoying that indices started at 1. Especially for implementing math concepts it was pretty weird because mathematicians often use 0-indexing as well (for example polynomials: a₀x⁰ + a₁x¹ + …).
In general I would suggest you to just get used to 0-indexing. It’s used by most programming languages and it is more efficient because the compiler doesn’t need to subtract 1 from all your indices.
By the way, thanks to multi-object for-loops you may not even need indices in zig. Here for example a string compare without any indices:
I understand that, just like Pascal (mentioned above), Lua has 1-based indexing, and remember many BASICs did too. I hope Zig (and all other languages) do NOT follow this convention ever, and stick to 0-based indexing.
I think all these 0-based vs 1-based indexing battles are happening because of some substitution of two concepts (offset and index). I’ll try to explain what I mean somehow.
‘Normal’ people are usually count things starting from 1. Programmers when they are not coding also do this. We have, say, 3 apples on a table and we are counting them like “one, two, three”, so that the number (index) of the last is equal to the total amount of things. But when these apples are arranged in a row… (as an array elements in computer memory), then offset come into the game.
1-st (index = 1) element has offset (measured in things) 0 from the startoffset
2-nd (index = 2) element has offset 1
and so on
So when we write a[i] (in C, Zig…) , i actually means offset from the beginning of an array, but we “tradionally” name it index. This is a bit of double-talk.
0-based is more natural for offsets
1-based is kinda more natural for indices.
0-based indexing is contra human brain. in slicing/substring(1, 5) the slice spans from element 2 through element 4. Neither 2 or 4 mentioned as parameters! it get more confusing when works it backward.
0-based indexing is contra human brain. in slicing/substring(1, 5) the slice spans from element 2 through element 4. Neither 2 or 4 mentioned as parameters! it get more confusing when works it backward.
Well thats fine and all. But I have found the opposite to be true for me. Perhaps it is just years of doing it that way, but I find it convinent and logical in surpricing ways. Not sure if I can account for any of those surprising ways from the top of my head. But to name one for the sake of nameing something, I find it handy that a arrays length is also the index of the would be next item. This can be handy when ranging over indexies say array a[… a.len], but this is of course a very contrived and simple example. I have just found working with 0-based indexes to be the right way to go. This could be better reasoned on my part, but there are probably better reasons to be found. In the end there is also a large subjective factor to these kinds of things.
Yes, I find myself too knowing that 0-based indexing has many nice benefits but they’re subtle little things that are hard enumerate in the spur of the moment. One little benefit that comes to mind is always knowing that when slicing (array[start .. end]) the length of the slice will always be end - start.