In the following c/c code,
int main()
{
int a[3] = {11, 22, 33};
int *p[3];
p[0] = &a[0];
p[1] = &a[1];
p[2] = &a[2];
printf("(*p)[2] = %d\n",(*p)[2]);
printf("*(p[2]) = %d\n",*(p[2]));
return 0;
}
It turns out that (*p)[2] = *(p[2]) = a[2].
So, I understand that with int *p[3];, I am creating an array of three pointers, and with the subsequent three lines after int *p[3];, I am putting the address of a[0] into p[0], address of a[1] into p[1], and address of a[2] into p[2].
Then, with *(p[2]), I am retrieving the variable pointed by the address stored in p[2], which makes *(p[2]) = a[2]. I have two questions regarding this simple code:
how to understand that
(*p)[2]also equalsa[2]?If p is no longer defined as an array of pointers to int variables, but an array of pointers to vectors of type int (
std::vectorin C ), does the equality(*p)[2] = *(p[2])still hold?
CodePudding user response:
*p is the same as p[0], which is a pointer to a[0]. So (*p)[2] is a[2].
p[2] is a pointer to a[2], so *(a[2]) is also a[2].
Nothing magical going on here. It's just the way you have set up your pointers.
CodePudding user response:
It's because your array of pointers is an array of pointers that all point within the same array.
(*p)[2] effectively expands to (&a[0])[2] (because &a[0] is in p[0]), reading the second element of a by starting from &a[0] and skipping two elements.
*(p[2]) effectively expands to *(&a[2]) (because &a[2] is in p[2]), which is equivalent to (&a[2])[0], reading the second element of a by starting from &a[2] and not skipping any elements.
Either way, you end up reading the value from a[2], the only question is whether you're dereferencing a pointer that doesn't point to a[2] at an offset, or dereferencing a precalculated pointer to a[2] without an offset. You could get the same result with p[1][1] as well, it just doesn't look quite as symmetrical with the other two use cases.
Regardless, all of this works because the definition of p is weird; it's a toy to illustrate how pointers and indexing work.
