← Back to context

Comment by lerno

2 days ago

Please consider a variable `List{int}[3] x`, this is an array of 3 List{int} containing List{int}. If we do `x[1]` we will get an element of List{int}, from the middle element in the array. If we then further index this with [5], like `x[1][5]` we will get the 5th element of that list.

If we look at `int*`, the dereference will peel off the `*` resulting in `int`.

So, the way C3 types are declared is the most inside one is to the left, the outermost to the right. Indexing or dereferencing will peel off the rightmost part.

C uses a different way to do this, we place `*` and `[]` not on the type but on the variable, in the order it must be unpacked. So given `int (*foo) x[4]` we first dereference it (from inside) int[4], then index from the right.

If we wanted to extract a standalone type from this, we'd have `int(*)[4]` for a pointer to an array of 4 integers. For "left is innermost", the declaration would instead be `int[4]*`. If left-is-innermost we can easily describe a pointer to an array of int pointers (which happens in C3 since arrays don't implicitly decay) int*[4]*. In C that be "int*(*)[4]", which is generally regarded as less easy to read, not the least because you need to think of which of * or [] has priority.

That said, I do think that C has a really nice ordering to subscripts, but it was unfortunately not possible to retain it.

Thanks for pointing out what I was missing.

Please consider a variable `List{int}[3] x`, this is an array of 3 List{int} containing List{int}. If we do `x[1]` we will get an element of List{int}, from the middle element in the array. If we then further index this with [5], like `x[1][5]` we will get the 5th element of that list.

I get that motivation. In C++ it's an odd case that where `std::vector<int> x[4]` is "reversed" in a sense compared to `int x[4][100]`. And this quirk is shared with other languages (Java, C#).

But in my experience, mixing generic datatypes like this with arrays is quite rare, and multi-dimensional array like structures with these types is often specified via nesting (`std::vector<std::vector>>`) which avoids confusion.

The argument re. pointers is more convincing though.