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.