@SuricrasiaOnline I'm curious what "array[i] == i[array]" is referring to specifically but search engines are not equipped for that kind of query.

· · Web · 2 · 0 · 1

@oakreef @SuricrasiaOnline

in C, array[i] and i[array] are equivalent. In the end of the day, it's just *(array+i).

Though I'm not sure how this is affected by element size...

@wolf480pl @oakreef @SuricrasiaOnline adding 1 to a pointer increments it to point to the next item. So on x86 (or most risc) given `u32 *p = ...; u32 *q =p +1;`, p and q will differ by 4 if you cast them to intptr_t.

(There are some obscure ISAs where this isn't true, but few people try to run off-the-shelf C code on those, these days. The ones I'm aware of are AS/400, Cray UNICOS, and the TI DSP families. Even on those, when they have a C compiler, the equivalency a[i] == i[a] still holds.)

@eqe @oakreef @SuricrasiaOnline hmm I guess if one of the things being added is an integer, there's no doubt whose element size should be taken. It's not like you're doing array1[array2]

@wolf480pl @oakreef @SuricrasiaOnline yep, exactly! Lots of things in C turn into integers automatically, but not pointers.

A partial list of things you can index into a C array with:

Characters, tbl['a']
booleans, tbl[x==3]
floating point I think? tbl[sin(x)]

And strings are also treated as pointers, so you can do
c = "abcde"[4]
Combining that with the original curséd syntax we have
c = 4["abcde"]

@eqe @wolf480pl @SuricrasiaOnline I'm afraid I'm not familiar with C so this is hard to parse for me. Most my coding experience is higher level stuff like C# and Python.

I know that an asterisk indicates that you're referencing a pointer. So given a pointer p that references 32 bit unsigned integer and another pointer q that references an integer one higher than q...

then you've lost me.

@oakreef @eqe @SuricrasiaOnline

ok, let's say you have a function like this:

```
void foo(uint8_t array[]) {
// ...
}
```

`array` here is actually a pointer to a chunk of memory with 8-bit unsigned ints, one after another.

`*array` dereferences array, and gives you the uint8_t that the pointer points to, i.e. 0-th element of the array

so `*array` is the same as `array[0]`

1/

@oakreef @eqe @SuricrasiaOnline

now, you can get a pointer to the 1-th element by just increasing `array` by one:
`ptr_to_1th = array + 1`
and dereference it:
`*ptr_to_1th`

or just: `*(array + 1)`

this is the same as `array[1]`.

Now, because C treats `a[b]` as just a syntactic sugar for `*(a + b)`, `1[array]` works equally well.

Now the surprising part is if you have array whose elements are bigger than 1-byte

2/

@oakreef @eqe @SuricrasiaOnline

btw. `uint8_t array[]`, when used in function arguments, is just syntactic sugar for:
`uint8_t* array`
i.e. a pointer to uint8_t.

Now if you have an array of uint32_t like:
`uint32_t array[]`
or
`uint32_t* array`

you'd still want `array[1]` to refer to the 1th element and not 3 bytes of 0th element and 1 byte of 1th element.

But C sees it as:
`*(array + 1)`
so here's the trick:

3/

@oakreef @eqe @SuricrasiaOnline

if array is of type uint32_t*,
then adding one to it advances it by sizeof(uint32_t), in this case 4.

so `array+1` is 4 bytes after `array`, and all is well.

Same for `1+array`.
Same for `1[array]`

I hope this helps.

4/4

@wolf480pl Thank you very much for taking the time to explain it to me!

@oakreef @SuricrasiaOnline array syntax in C is just pointer arithmetic:

array[i] is the same as *(array + i) is the same as i[array] (for certain types of array and i, I think?)
Sign in to participate in the conversation
🍏Abhlach🍎

Personal server of https://abhlach.ie/@oakreef