Я пытаюсь понять, почему доступ к первому блоку осуществляется с помощью:
int* address = (int*)((int)&pool->data + pool->offset);
особенно часть (int)&pool->data
. Не является ли pool->data
уже
указатель
Да, pool->data
- указатель. И можно получить адрес указателя, так что в этом нет ничего плохого. Результат в этом случае имеет тип void **
.
Более того, учитывая, что data
является первым членом struct mempool
, &pool
будет указывать на тот же адрес. Хотя последний имеет другой тип (struct mempool *
), вероятно, это связано с тем, что код выполняет преобразование в тип int
.
зачем мне нужен его адрес для выполнения арифметики и перехода к
смещение?
В результате вычисляется адрес относительно местоположения самого указателя data
, а не относительно его target . Кроме того, приведение к типу int
предполагает, что смещение измеряется в байтах. Однако этот аспект немного небезопасен, поскольку не гарантируется, что тип int
достаточно велик для поддержки преобразования туда и обратно из указателя в int
в указатель.
Все это, похоже, согласуется с вашей характеристикой пула, имеющего метаданные рядом с данными, но остается неясным, для чего служат указатели data
.
В целом, хотя я не уверен в правильности или эффективности представленного минимального кода. Если он действительно служит той цели, для которой он предназначен, относительно представленного определения структуры, то этот вариант должен быть лучше и понятнее:
int* address = (int*)((char *)&pool + pool->offset);
Это позволяет избежать вопроса о целочисленном типе, который может представлять указатели (хотя есть один в форме intptr_t
). Приведение к char *
учитывает тот факт, что арифметика указателя выполняется в единицах, равных размеру указываемого типа, а смещение представляется в однобайтовых единицах.