Лучший способ статически инициализировать связанный список в C? - PullRequest
3 голосов
/ 02 февраля 2020

У меня есть односвязный тип списка, который выглядит следующим образом:

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

Ответы [ 2 ]

6 голосов
/ 02 февраля 2020

Вместо того, чтобы объявлять 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;
1 голос
/ 02 февраля 2020

Мне нравится решение 1201ProgramAlarm, но если вы этого не сделаете, как небольшое улучшение вашей формы, вы можете поставить каждую закрывающую скобку на отдельной строке. Это «тратит впустую строки», но это делает ваши различия симметричными c и + -только, а не

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

или подобными.

Я бы также подумал, будет ли это даже имеет смысл использовать связанный список, который не является изменяемым. Это может , если есть интерфейс, который вам нужно передать, который принимает только связанные списки. Но в остальном массив является строго превосходящей структурой данных для неизменяемого списка.

...