在C语言中静态初始化链表的最佳方法是什么?

5

我有一个单向链表类型,长这样:

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);

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

8
与其声明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让我头疼。 :) - grebneke

1
我喜欢1201ProgramAlarm的解决方案,但如果您不喜欢,作为对您的表单的小改进,您可以将每个闭合括号放在自己的一行上。这样做“浪费了行数”,但它使您的差异对称且仅包含+,而不是。
-}}}}}};
+}}}}}}};

或类似的。

我也会考虑是否有必要使用不可变的链表。如果有需要将其传递给仅接受链表的接口,则可能需要使用它。但是,对于不可变列表,数组是一种严格优越的数据结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接