У меня возникли проблемы с интерпретацией этого двусвязного списка:
struct _dnode {
union {
struct _dnode *head;
struct _dnode *next;
};
union {
struct _dnode *tail;
struct _dnode *prev;
};
};
typedef struct _dnode sys_dlist_t;
typedef struct _dnode sys_dnode_t;
И в этом списке определены дополнительные функции, например, определение того, является ли данный узел головным в списке:
static inline int sys_dlist_is_head(sys_dlist_t *list, sys_dnode_t *node)
{
return list->head == node;
}
Теперь мои вопросы -
(i) Зачем нам нужен союз здесь? Тоже таким специфическим образом?
(ii) Почему list
и node
в списке будут указателями одного и того же типа? (см. декларацию typedef
)
(iii) Если я объявлю список такого типа, т.е. элементы data_node
будут элементами типа sys_dlist_t
:
struct data_node{
sys_dnode_t node;
int data = 0;
} data_node[2];
и я объявляю узел так, что:
sys_dnode_t *node = NULL;
а затем, если я хочу выполнить итерацию по своему списку, чтобы проверить, соответствует ли data
элемента data_node
, скажем, числу 3. Могу ли я сделать это, приведя node
(который в настоящее время является указателем на тип sys_dnode_t
) к указателю на тип data_node
?
Теперь в коде это было сделано, и это выглядит так:
if (((struct data_node *)node)->data == 3) {
break;
}
Это сбивает меня с толку. Возможно, я пропустил какой-то код, чтобы понять это, поэтому, пожалуйста, сообщите мне, если вам нужна дополнительная информация. Можем ли мы привести указатель типа node
к некоторой структуре, содержащей node
, а затем получить доступ к другим данным структуры? Как это работает?
EDIT 1: Еще немного информации в этом списке:
"Ожидается, что списки будут инициализированы таким образом, что оба указателя: начало и конец указывают на сам список. Инициализация списков таким образом упрощает добавление и удаление узлов в списке и из него."
Инициализация выглядит следующим образом:
static inline void sys_dlist_init(sys_dlist_t *list)
{
list->head = (sys_dnode_t *)list;
list->tail = (sys_dnode_t *)list;
}
iii
структураdata_node
— это способ эмулировать наследование в C. - person Some programmer dude   schedule 04.04.2018sys_dlist_is_head
должно быть сравнение сtail
? - person freestyle   schedule 04.04.2018i
: есть тонкое отличие от повторного использования и неправильного использования. В 80-х идея повторного использования заключалась в том, чтобы писать как можно меньше кода. Однако список не является узлом, но список содержит узлы или список содержит ссылки на головной и хвостовой узлы, поэтому в современных реализациях списков понятия (классы/структуры) списка и узлов обычно хранятся разделенными, с большим количеством кода написанный, но не написанный обескураживающий код (читай: приведение типов). Тот факт, что узел и список имеют одинаковую форму (два указателя на узлы), недостаточен, чтобы позволить двум типам свернуть в один, сегодня, как правило, ИМХО. - person Sigi   schedule 11.04.2018