#Pointer arrays
26 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
foo[bar] is equivalent to (*(foo + bar)). this means (among other things) that foo[0] and (*foo) are equivalent; and that foo[bar], (*(foo + bar)), (*(bar + foo)), and bar[foo] are equivalent
Because array indexing is just a shortcut to pointer math. array[i] is the same thing as *(array + i). Note that the math inside the parens is pointer math, it says "multiply i by the size of the array type".
So say your allocation is int32_t *array = malloc(1024);, that is an allocation of 1024 bytes, but you address it in int32_t sized chunks (32-bits, 4 bytes).
array[0] is the base address of the allocation. array[1] is the base address, plus 32-bits (4 bytes).
array[1] is the same thing as *(array + 1) or "give me what is stored at array plus 32-bits (aka plus 4 bytes)"
The * is the dereference operator here. Note that array is a pointer variable, it stores a memory address. So when we want to get what is "at" that memory address, we dereference that pointer.
oh yeah, pointer math is (as far as i know) defined as foo + bar where foo is a pointer is equivalent to (typeof(foo))((uintptr_t)foo + bar * sizeof(typeof(*foo)))
No, pointer arithmetic is defined as indexing an array in the standard.
If ptr points to the ith element of an array, then ptr + n points to the i+nth element of the array
So all you're doing is treating the pointer as if it points to the 0th element of an array. Memory from malloc is blessed to be able to be treated like this
the standard doesn't require casting to size_t to mean anything
nor does it require that adding 1 and then casting back gets the next byte
adding 1 and casting back won't (necessarily) get the next byte. i agree that the code block i posted is obtuse and shouldn't have been posted on those grounds alone, but it adds (when bar == 1) 1 * sizeof(typeof(*foo)). if foo is a char*, then it will add 1. unless you mean to say that the compiler is allowed to add any number of padding bytes in an array?
does this mean that casting to size_t is UB, or implementation-defined? the latter i expect, but if the former -- well, 
i chose size_t because size_t is "the maximum size of an object", which (as i understand it) is the maximum size representable by the useful bits in a pointer
size_t is the upper bound addressable space on the architecture
@somber rune to answer your question:
int* x = malloc(sizeof(int) * 10);
this means we allocate sizeof(int) = 2 * 10 bytes.
that's 20 bytes.
x is a pointer that holds the beginning aggress of this memory region.
when you do:
x[idx]
it effectively means get the value at address: (x + (idx * sizeof(int)))
so it ends up just being pointer arithmetic.
happy to help.
you're not meant to cast a pointer to size_t
you're meant to use [u]intptr_t for such conversions, if it exists
ah, that makes sense then
i was trying to avoid what Shaharyar just did and provide an informative but technically incorrect answer. typing *(x + (idx * sizeof(int))) into a C program would result in multiplying idx by pow(sizeof(int), 2) in the generated assembly
corrected my answer, thank you.
in (x + (idx * sizeof(int))), typeof(x) is still int*, and will be treated as such by the pointer arithmetic. you'd have to either cast x itself to char* or uintptr_t to avoid that (i.e. ((char*)x + (idx * sizeof(int)))). not dereferencing the final value does avoid UB, though