我有一个单链表类型,如下所示:
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);
与其将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;
我喜欢1201ProgramAlarm 的解决方案,但如果你不这样做,作为对表单的一个小改进,你可以把每个右大括号放在它自己的行上。这"浪费了线条",但它使您的差异对称且仅+
,而不是
-}}}}}};
+}}}}}}};
或类似。
我还会考虑使用不可变的链表是否有意义。如果需要将其传递给仅接受链表的接口,则可能会如此。但除此之外,数组是不可变列表的严格高级数据结构。