Я пытаюсь найти способ хранить указатели void в блоках памяти через связанный список, и я наткнулся на это представление.
//Initalization
void * list;
//Add void pointer
void add_pointer(void * p) {
*(void **)p = list;
list = p;
}
//Remove pointer with address
void remove_pointer(void * p) {
void ** iter;
iter = &list;
while ((*iter != NULL) && (*iter != p)) {
iter = (void **)*iter;
}
if (*iter == p) {
*iter = *(void **)p;
}
}
Как это работает? Является ли адрес следующего блока сохраненным в предыдущих данных блока, на которые указывает указатель void? Предположим, что список инициализирован NULL.
Кроме того, предполагает ли это, что в каждом блоке указателя пустоты нет данных, записанных в нем? Если кто-нибудь может пролить свет на то, как эта реализация работает, это будет отлично, просто кажется очень эзотерическим, что он может функционировать как связанный список.
Предполагается, что первым полем в узле является слот для указателя ссылки, который является void *
. И list
- это void *
и он всегда указывает на головку связанного списка.
add_pointer()
добавляет новый узел в начало списка. Аргумент void *p
указывает на новый добавляемый узел. Функция передает void *
p в void **
так что *(void **)p
может содержать указатель void *
. Функция сохраняет предыдущий указатель главы в этом месте как
*(void **)p = list; // list is a void * to the first element
Затем он устанавливает list
как void *
в новый первый элемент, т.е. P.
Теперь remove_pointer()
удаляет узел из списка, принимая в качестве аргумента void *
указывающий на него. iter
используется для итерации списка. Первоначально ему присваивается адрес list
так что *iter
будет указывать указатель ссылки, который считается первым полем в узле. Обновления в то время как петля iter
к следующему узлу в списке до тех пор, пока не найдет p
(который является узел, чтобы быть удален) в указателе ссылки области текущего узла. На этом этапе он обновляет указатель на ссылку, указанный в текущем узле, чтобы указать на значение поля указателя ссылки узла, на которое указывает p, что делается с помощью инструкции
*iter = *(void **)p; // *iter gives the link pointer filed of the current node
// p, is the node to be removed, *(void **)p gives the value in
// the link pointer filed of p
Это просто делает предположение, что самое первое поле узла является слотом для указателя ссылки. Он переводит указатель на узел (void**)
чтобы он мог хранить void*
по этому адресу.
И, конечно, list
- это жестко закодированное местоположение для указателя на первый узел в связанном списке.
Не самый гибкий дизайн списка.
add_pointer()
не волнует, что было в ссылке - первое, что он делает - перезаписывает ссылку 'поле' указателем вlist
.