More Messing with Array Subscripts

I’ve written before about array subscripts and how they’re secretly expressions. But another weird aspect of array subscripts also looms on the horizon: The format a[1] can be written as 1[a].

Before I explain what’s going on, here’s sample code:

2024_08_31-Lesson-a.c

#include <stdio.h>

int main()
{
    int a[] = { 1, 2, 3, 4, 5 };

    printf("%d\n",a[2]);
    printf("%d\n",2[a]);

    return 0;
}

The two printf() statements use both forms to access the third array element, traditionally written as a[2]. Here’s the output:

3
3

Both arrangements generate the same result, accessing the third element in array a[]. But how?

You’re probably aware of the weird relationship between pointers and arrays. They aren’t the same thing; array notation isn’t shorthand for pointer notation. The big difference is how the compiler stores the data in memory. Regardless, internally the compiler uses pointer offsets to access array elements.

For example, a[2] translates into *(a+2). Because this translation takes each part of the array notation and shoves it into the pointer format, when you write 2[a] you get *(2+a).

Yes, the expression *(2+a) looks awkward, but the math is the same as *(a+2). You can use either format to obtain the same result.

The weirder thing, which harkens to my earlier blog post, is whether this format works with expressions. Here’s the code I used to test:

2024_08_31-Lesson-b.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    int a[] = { 10, 20, 30, 40, 50 };

    srand( (unsigned)time(NULL) );
    printf("%d\n", (rand()%5)[a] );

    return 0;
}

This code updates code presented in the Lesson from May. The expression rand()%5 generates a random value from 0 through 4. It’s prefixed before the brackets with the array name inside the brackets. The expression is enclosed in parentheses, otherwise the compiler would try to fetch the non-existent fifth element from array a[]. (The order of operations binds the 5 tight to the brackets.)

The output shows a random element from the array, just as if the expression rand()%5 were in the brackets. So it works!

While I’m delighted in the funky nature of swapping an array name with its element number (or expression), I would never use such a format in my code. Yes, it’s wonderfully cryptic. Obfuscators would enjoy using this trick, but I aim for readable code.

A bigger question, one that I haven’t attempted, is whether this trick works in Python or other languages. It’s not that using the backwards format does anything special, just that such things are entertaining to nerds such as myself.

Leave a Reply