正确使用带结构的指针

时间:2016-07-12 10:04:44

标签: c pointers struct

在:

之间是否存在任何差异(表现/正确性/良好做法)

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

如何"双指针"方案整合了两个定义?

2 个答案:

答案 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*发送到函数,以便能够清除头指针。在这种情况下,获得元素的间接数量相同。