在:
之间是否存在任何差异(表现/正确性/良好做法)选项1:
typedef struct node{
int value;
struct node *next;
}*Node;
typedef struct linkedlist{
Node head;
}*LinkedList;
选项2:
typedef struct node{
int value;
struct node *next;
}*Node;
Node head = NULL;
如何"双指针"方案整合了两个定义?
答案 0 :(得分:1)
与评论所说的相反,typedef
指针不是总是一个坏主意。在某些情况下,您希望隐藏实现细节并通过句柄提供功能。在这些情况下,通常会看到所谓的opaque pointer类型。
示例:
在 LinkedList.h
中typedef void *LinkedList;
LinkedList LinkedList_Create();
void LinkedList_AddFirst(LinkedList list, void *element);
在 LinkedList.c
中struct linkedList {
/* head, tail, size, ... */
};
LinkedList LinkedList_Create() {
struct linkedList *plist = malloc(sizeof(struct linkedList));
/* error checking, initialization */
return plist;
}
void LinkedList_AddFirst(LinkedList list, void *element) {
struct linkedList *plist = (struct linkedList *) list;
/* your code here */
}
这种方法的缺点是你需要显式地将typedef
'd指针强制转换为内部类型,但这不会导致性能更差,因为C不提供运行时类型检查。
从最佳实践的角度来看,如果您不需要隐藏实施细节,通常最好不要typedef
指针。当然,它可能会使您的代码更加冗长,但这样您始终知道您正在处理的类型。通常,typedef
不应隐藏基础类型,而只是为其提供别名。
如果您有兴趣了解C语言中的最佳实践,请参阅Linux内核的编码风格指南,您可以找到here。
答案 1 :(得分:0)
是的,似乎有所不同。首先,您没有展示您打算如何使用LinkedList
,但无论如何,在第一个选项中获取数据还需要一个间接级别。
假设您在选项1中使用LinkedList
作为:
LinkedList lst;
然后为了获取列表中的第一个节点(如果它为空,则为NULL
),您必须使用lst->head
,而在第二个选项中,您只需使用head
直。这意味着第二种选择稍微有效(在某些情况下)。
但是在第二个选项中,您必须发送一个指向head
的指针,以便将其传递给一个整体修改列表的函数。例如,清空列表的函数必须能够修改指向列表头部的指针,以便将其设置为NULL
(是的,它也必须free
节点,但这不是点)。在第一个选项中,您可以通过arg->head = NULL
执行此操作,但在第二个选项中,您必须将Head*
发送到函数,以便能够清除头指针。在这种情况下,获得元素的间接数量相同。