2016-07-12 41 views
0

指针是否有任何差异(性能/正确性/好的做法)之间:正确使用与结构

选项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; 

“双指针”方案如何整合两个定义?

+8

是的,'typedef'指针几乎总是一个非常糟糕的想法.... –

+0

你指的是选项1,'struct linkedlist'?为什么这是一个坏主意? –

+4

这两种情况都有。 'tyedef'-ed类型不带指针符号,使后面的用法更不易读。 –

回答

0

是的,似乎有区别。首先,你没有展示你打算如何使用LinkedList,但无论如何,在第一个选项中需要一个更多的间接级别来获取数据。

让我们假设你在选择一个将使用LinkedList为:

LinkedList lst; 

那么为了获得该列表中的第一个节点(或NULL,如果它是空的),你将不得不使用lst->head,而在您将直接使用head的第二个选项。这意味着第二种方法效率稍高一些(在某些情况下)。

但是,在第二个选项中,您必须发送一个指向head的指针,以便将它传递给一个修改整个列表的函数。例如,清空列表的函数必须能够修改指向列表头部的指针,以便将其设置为NULL(是的,它也必须是free节点,但那不是重点)。在第一个选项中,您可以简单地通过arg->head = NULL来完成此操作,但在第二个选项中,您必须将Head*发送到该功能,以便它能够清除头指针。在这种情况下,会有相同数量的元素间接指向。

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 */ 
} 

这种方法的缺点是,你需要明确地投指向你内部类型的d指针,但这不会重新由于C没有提供运行时类型检查,所以性能更差。

从最佳实践的角度来看,如果您不需要隐藏实施细节,通常最好不要typedef指针。当然,这可能会让你的代码更加冗长,但这样你总是知道你正在处理的是什么类型。一般来说,typedef不应该隐藏基础类型,而只需为其提供别名。

如果您有兴趣了解更多关于C最佳实践的知识,请参阅Linux内核的编码风格指南,您可以找到here

+0

你可以在不隐藏指针语义的情况下实现一个不透明的句柄。这实际上是你发布的维基百科页面所做的。这个成语中的结构不透明,而不是指针。在大多数情况下,使用'void *'而不是forward来声明结构也是不必要的麻烦。 – StoryTeller

+0

谢谢你指出。虽然,我的推理是,如果你需要隐藏底层类型,你可能也想隐藏它是一个结构的事实。虽然,文章中描述的方法确实有其优点,因为它使调用者可以处理分配。 –

+0

是的,你可能想要完全隐藏底层类型(void *实际上可能包含一个用于内部映射的int,而不是实际的指针)。 **但是**你不应该为了隐藏类型而隐藏该类型。 (既然你提到了Linux内核,[Linus对此也有意见](http://yarchive.net/comp/linux/typedefs.html),他的平常风格) – StoryTeller