One-based array index

Using one-based array index proved for me to be very convenient. I hope you consider that in Zig.

Would you elaborate on that?
Why 1-based, specifically?

IIRC, there was a language (Pascal?) that allowed to specify any index base for specific arrays. Anyway, it’s just syntactic sugar, IMO.

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

yes, no problem:

#include <stdio.h>

float a[] = {
    [0] = 1.1,
    [1] = 2.2,
    [2] = 3.3,
};

int main(void) {
    printf("a[2] = %.1f\n", a[2]);
    printf("2[a] = %.1f\n", 2[a]);
}
$ ./a.out 
a[2] = 3.3
2[a] = 3.3

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.

You can try it out here.

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.

I do not understand this either.

@dude_the_builder, got it!
Is zig supported?

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 tried Pascal, pascal and pas, but it didn’t work.
Anyway, I doubt we’ll see much Pascal in this forum.

Confirmed, there’s no Pascal syntax highlighting. Bad news for you old timers. lol

1 Like

It is a purpose of syntactic sugar to simplify how a code looks like, isn’t it?..
Still, in C a[j][k] is sugar for *(*(a + j) + k):

#include <stdio.h>

float a[3][3] = {
    [0] = {[0] = 1.1, [1] = 2.2, [2] = 3.3},
    [1] = {[0] = 4.4, [1] = 5.5, [2] = 6.6},
    [2] = {[0] = 7.7, [1] = 8.8, [2] = 9.9},
};

int main(void) {

    int j = 1;
    int k = 1;
    printf("a[%d][%d] = %.1f\n", j, k, a[j][k]);
    printf("a[%d][%d] = %.1f\n", j, k, *(*(a + j) + k));
}

and output:

$ ./a.out 
a[1][1] = 5.5
a[1][1] = 5.5
1 Like

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:

for(stringA, stringB) |a, b| if(a != b) return false;
return true;
3 Likes

Got it. Thank you for the clarifying.

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 really cringe when I need to program in one-based index programming languages. It would be horrible if zig would do that.

1 Like

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.

1 Like

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.

Exactly!

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.

When I heard of 1-based indexing for the first time my reaction was, WHAT! When I tried it I realized it was way more convenient than 0-based one.