I'm trying to understand why accessing the first block is done by:
int* address = (int*)((int)&pool->data + pool->offset);
especially the (int)&pool->data
part. Isn't pool->data
already a
pointer?
Yes, pool->data
is a pointer. And one can obtain the address of a pointer, so there's nothing inherently wrong with that. The result in this case has type void **
.
Moreover, given that data
is the first member of struct mempool
, &pool
would point to the same address. Although the latter has a different type (struct mempool *
), that's probably mooted by the fact that the code performs a conversion to type int
.
why do I need its address to perform arithmetic and shift to
the offset?
The effect is to compute an address relative to the location of the data
pointer itself, rather than relative to its target. Furthermore, the cast to type int
suggests that the offset is measured in bytes. That aspect of it is a bit unsafe, however, because it is not guaranteed that type int
is large enough to support round-trip conversion from pointer to int
to pointer.
This all seems consistent with your characterization of the pool having metadata adjacent to the data, but it remains unclear what purpose the data
pointers serve.
Overall, although I'm not convinced of the correctness or efficacy of the minimal code presented. If it in fact serves the purpose for which it is intended, relative to the structure definition presented, then this variation should do so better and more clearly:
int* address = (int*)((char *)&pool + pool->offset);
That avoids the question of an integer type that can represent pointers (although there is one in the form of intptr_t
). The cast to char *
accounts for the fact that pointer arithmetic is performed in units the size of the pointed-to type, and the offset seems to be expressed in one-byte units.