【问题标题】:Best way to statically initialize a linked list in C?在 C 中静态初始化链表的最佳方法?
【发布时间】:2020-02-02 00:55:10
【问题描述】:

我有一个如下所示的单链表类型:

struct point { int x, y; };
struct point_list {
    struct point value;
    const struct point_list *next;
};

我想静态初始化这些列表之一,可能有几十个条目。我想每行写一个具有一致缩进的项目,以便于编辑列表。

到目前为止,我想出的最好的是:

const struct point_list *const my_list =
    &(const struct point_list) { .value = { 1, 2 }, .next =
    &(const struct point_list) { .value = { 3, 4 }, .next =
    &(const struct point_list) { .value = { 5, 6 }, .next =
    NULL
    }}};

但缺点是:

  • 当我添加或删除项目时,我需要更新最后一行的右大括号数。
  • 可能很难说服代码格式化程序保持这种风格。

有没有更好的办法?

如果我们有递归宏,也许这样的东西可以工作:

const struct point_list *const my_list = POINT_LIST(
    ((struct point) { 1, 2 }),
    ((struct point) { 3, 4 }),
    ((struct point) { 5, 6 }),
);

如果我们可以在编译时运行代码,也许这样的事情可以工作:

#define array_length(X) (sizeof(X) / sizeof(X[0]))

constexpr const struct point_list *array_to_list(size_t length, struct point *values) { ... }

const struct point my_array[] = {
    { 1, 2 },
    { 3, 4 },
    { 5, 6 },
};
const struct point_list *const my_list = array_to_list(array_length(my_array), my_array);

【问题讨论】:

  • 成员声明const struct point *next;应该是const struct point_list *next;吗?
  • 静态创建链表的目的是什么?您永远不能从列表中删除节点。
  • @Gerhardh:可以在静态元素之前插入其他元素。或者,它可以传递给采用链表的例程,该链表也与动态创建的列表一起使用。
  • 谢谢,const struct point *next; 是个错误。 (那不会是一个链接列表!)我已经编辑了那行。
  • 是的,我正在使用链接列表,因为我想(非破坏性地)在运行时扩展列表。我可以使用数组的链表,或者最终节点是数组的链表,但我不想为了使初始化程序更好而使数据结构复杂化。

标签: c c11


【解决方案1】:

与其将my_list 声明为指针,不如将其声明为数组:

struct point_list const my_list[] = {
    { .value = { 1, 2 }, .next = &my_list[1] },
    { .value = { 3, 4 }, .next = &my_list[2] },
    { .value = { 5, 6 }, .next = NULL }
};

如果你仍然希望my_list 是一个指针,你可以做类似的事情:

static struct point_list const my_list_data[] = {
    // ...
};
const struct point_list *const my_list = my_list_data;

【讨论】:

  • 我喜欢这个答案,最后一行的双 const 让我头疼。 :)
【解决方案2】:

我喜欢 1201ProgramAlarm 的解决方案,但如果您不喜欢,作为对表单的小改进,您可以将每个右大括号放在自己的行上。这“浪费线”,但它使您的差异对称且仅+,而不是

-}}}}}};
+}}}}}}};

或类似的。

我还会考虑使用不可变的链表是否有意义。 可能 如果您需要将其传递给只接受链表的接口。但除此之外,对于不可变列表,数组是一种严格意义上的高级数据结构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 2014-12-11
    相关资源
    最近更新 更多