Фон
Я создал основную структуру данных связанных списков, в основном для обучения. Одна из целей этого списка заключалась в том, что он может обрабатывать разные структуры данных. Поэтому я попробовал свои силы в составе структуры, чтобы имитировать "наследование" в C. Вот структуры, которые составляют основу для моего связанного списка.
typedef struct Link {
struct Link* next;
struct Link* prev;
} Link;
typedef Link List;
В моей реализации я решил иметь часовое node, которое служит как головой, так и хвостом списка (вот почему Link == List).
Чтобы сделать список действительно обрабатываемым данными, структура просто включает в себя структуру Link в качестве первого элемента:
typedef struct {
Link link;
float data;
} Node;
Таким образом, связанный список выглядит следующим образом.
┌───┬───┬───┐ ┌───┬───┐ ┌───┬───┬───┐
... <--->│ P │ N │ D │<--->│ P │ N │<--->│ P │ N │ D │<---> ...
└───┴───┴───┘ └───┴───┘ └───┴───┴───┘
End Node myList First Node
List myList;
Node node1 = {{}, 1.024};
....
Node nodeN = {{}, 3.14};
list_init(&myList) // myList.next = &myList; myList.prev = &myList;
list_append(&myList, &node1);
....
list_append(&myList, &nodeN);
Вопрос
Чтобы пройти этот список, указатель Node
сначала указывает на Первый Node. Затем он перемещается по списку, пока он снова не укажет на часового, а затем остановится.
void traverse()
{
Node* ptr;
for(ptr = myList.next; ptr != &myList; ptr = ptr->link.next)
{
printf("%f ", ptr->data);
}
}
Мой вопрос заключается в строке ptr != &myList
. Есть ли проблема выравнивания указателя с этой строкой?
Цикл for корректно создает предупреждения: (warning: assignment from incompatible pointer type
и warning: comparison of distinct pointer types lacks a cast
), которые можно отключить, выполнив то, что он говорит, и произнесение на Node*
. Однако, это DumbThingToDo ™? Я никогда не получаю доступ к ptr->data
, когда он указывает на &myList
, когда цикл завершается один раз ptr == &myList
.
TL;DR
В C-структурах a Base*
может указывать на Derived
, если Base
является первым членом в Derived
. Может ли Derived*
указывать на Base
, если ни один из Derived
не доступен для определенных членов?
EDIT: замените соответствующие вызовы функций их эквивалентным встроенным кодом.