6 ms·
Reading through, something small caught me by surprise. https://c3-lang.org/language-common/arrays/#fixed-size-multi-dimensional-arrays https://c3-lang.org/lan
by xen0 9mo ago
Reading through, something small caught me by surprise.
https://c3-lang.org/language-common/arrays/#fixed-size-multi-dimensional-arrays https://c3-lang.org/language-common/arrays/#fixed-size-multi...
Multi dimensional arrays are not declared in the same way they are accessed; the order of dimensions is reversed.
Accessing the multi-dimensional fixed array has inverted array index order to when the array was declared.
That is, the last element of 'int[3][10] x = {...}' is accessed with 'x[9][2]'.
This seems bizarre to me. What am I missing? Are there other languages that do this?
- sph 9mo agoFile it with the footgun of the two different array slicing syntaxes: https://c3-lang.org/language-common/arrays/#slicing-arrays https://c3-lang.org/language-common/arrays/#slicing-arrays I have already opened a discussion about this with the author, and I must say I agree to disagree that a language needs arr[start..end] (inclusive) as well as arr[start:len] (up to len-1) and if you use the wrong one, you’ve now lost a foot and your memory is corrupted.
- xen0 9mo agoThe closed intervals for slices caught my eye as well, but I simply filed that under 'that's a weird quirk' rather than 'wtf?'. It would require more thinking on my end to change that to either 'this is an acceptable choice' or 'this is a terrible idea'. But the array indices being reversed on declaration? I cannot think of an upside to that at all.
- deleted 9mo ago[deleted]
- lerno 9mo agoPlease 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.
- xen0 9mo agoThanks 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.