【问题标题】:Can data structures be completely abstracted in C?数据结构可以在C中完全抽象吗?
【发布时间】:2013-06-08 18:56:47
【问题描述】:

我目前正在构建一个数据结构的个人库,我意识到它们可以通过将其中的数据完全抽象为 void *.所以假设我创建了一个链表

typedef struct node_ll {
    void *data;
    struct node_ll *next;
} node_ll;

假设我正在创建一个结构链接列表,它们被定义为

struct person {
    char *name;
    int age;
};

那么,是否可以定义一个抽象的搜索方法

void *traverse(void *head, void* data) {}

要找到一个 19 岁且名叫“约翰”的人?

【问题讨论】:

  • 有可能,但很容易出错。看看stackoverflow.com/a/351756/1944441,说的书不好理解。
  • 也可以传递一个函数指针来处理void *指向的数据类型。
  • 这是可能的,但是你失去了类型安全性。你最好远离 C 并查看 C++ 的标准模板库,甚至更好地在 Haskell 中启动程序。
  • @BryanOlivier 你可以让它打字安全。
  • @Armin 可能,但您是否同意其他建议;)?

标签: c data-structures linked-list traversal abstraction


【解决方案1】:

要使您的列表数据结构抽象化,只需将node_ll 结构的定义隐藏在源文件中即可。头文件只包含前向声明和 API 原型:

typedef struct node_ll node_ll;
typedef struct linkedlist { node_ll *head; } linkedlist;

static inline linkedlist make_linkedlist () {
    const linkedlist zero_ll = { 0 };
    return zero_ll;
}
void unmake_linkedlist (linkedlist *list);

void linkedlist_add (linkedlist *list, void *data);
void linkedlist_traverse_until (linkedlist *list,
                                int (*visit)(void *visit_data, void *data),
                                void *visit_data);

linkedlist_traverse_until() 函数基本上会在每个节点上调用提供的visit() 函数,除非visit() 返回 0,此时它会停止。该函数的实现知道如何访问node_ll,因为它位于具有struct node_ll 完整定义的源文件中。

while (node) {
    if (visit(visit_data, node->data)) {
        node = node->next;
        continue;
    }
    break;
}

【讨论】:

  • 所以基本上我有一个 structure.h 文件,它定义了数据结构类型的原型,我为每个实现定义了该数据结构,并且还在该实现中定义了一个遍历方法?跨度>
  • 你不必在头文件中完全定义结构,只要所有API只使用指向前向声明的指针即可(指针是完整的类型)。源文件(即.c 文件)包含拼写出的结构定义(在您的帖子中包含datanext 成员),以便API 的实现可以访问这些成员。
  • 您知道网上有哪些完整的工作示例可以进一步说明这一点吗?
  • 不适用于链表,但有一个red-black tree implementation 使用了这个想法。通常,不透明数据类型很常见。 UNIX 文件描述符概念本质上是一种不透明类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
  • 2010-09-20
  • 1970-01-01
  • 2010-09-14
  • 2016-05-05
  • 1970-01-01
  • 2018-09-03
相关资源
最近更新 更多