【发布时间】:2015-03-26 14:32:07
【问题描述】:
背景
我创建了一个基本的链表数据结构,主要用于学习目的。该列表的一个目标是它可以处理不同的数据结构。因此,我尝试使用结构组合来模拟 C 中的“继承”。以下是构成我的链表基础的结构。
typedef struct Link {
struct Link* next;
struct Link* prev;
} Link;
typedef Link List;
在我的实现中,我选择了一个哨兵节点作为列表的头部和尾部(这就是为什么 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 指针最初指向第一个节点。然后它沿着列表遍历,直到它再次指向哨兵然后停止。
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 终止一次。
TLDR
在 C 结构中,如果 Base 是 Derived 中的第一个成员,则 Base* 可以指向 Derived。如果没有Derived 特定成员被访问,Derived* 是否可以指向 Base?
编辑:用等效的内联代码替换相关的函数调用。
【问题讨论】:
-
与问题本身无关,我只想说演示文稿是 stellar。
-
我认为您不会遇到指针对齐问题,但我会问:为什么不将
List设为Node的别名,而忽略data成员的 @987654343 @?或者直接将其设为Node(定义Node myList;而不是List myList;)这将是避免指针转换问题的一种更简洁的方法。我同意另一条评论:干得好,清楚地说明问题。 (+1) -
&myList不是Node*,它是指向Node *或Node **的指针。我认为您需要将第二个变量设置为list_first(&myList)或者只是在for中调用list_first(&myList)并希望编译器能够优化。 -
我的问题中有内联 list_first() 和 link_next()。
-
@lurker 我考虑定义 Node myList 但它只是似乎列表应该是
List类型;)。
标签: c pointers data-structures linked-list