инициализировать связанный список во время компиляции

#c #struct

Вопрос:

у меня есть следующая структура:

 struct node {
    char *data;
    struct node *next;
};
 

Я хочу инициализировать его некоторыми уже известными значениями.

Например:

 struct node {
    char *data;
    struct node *next;
} *root = amp;(struct node){"data1", amp;(struct node){"data2", NULL}};
 

Можно ли получить адрес структуры, содержащей «data2»?
или назначить root структуре, содержащей «data2»?

Редактировать:

Я хочу сделать следующее во время компиляции с составными литералами:

 struct node *b = amp;(struct node){"data2", NULL};
struct node *a = amp;(struct node){"data1", b};
a = b;
 

Правка2:

что-то вроде того:

 struct node {
    char *data;
    struct node *next;
};
struct node *tmp, *root = amp;(struct node){"data1", tmp = amp;(struct node){"data2", root}};
root = tmp;
 

но я не хочу, чтобы tmp существовал во время выполнения

Комментарии:

1. Вопрос довольно неясен. Работает ли ваш код? Если нет, то в чем заключается ошибка или нежелательное поведение?

2. root имеет тип struct node * , поэтому он не может указывать на поля next или data экземпляра struct node , не обходя систему типов (и даже если бы это было возможно, это было бы бесполезно). Если у вас есть фактический экземпляр struct node (в отличие от простого указателя), вы можете указать на него указатель или присвоить указателю текущее значение next поля. Но в опубликованном коде нет экземпляра.

3. Осурсолл, как насчет struct node root1 = {"Hello World", amp;root1}; . amp;root1 может быть использован в более позднем коде, где требуется указатель.

4. static struct node {...} a = { 'a', 0 }, b = { 'b', amp;a }, c = { 'c', amp;b }; работает clang -Wall -Wextra -pedantic -Weverything , но я все еще не уверен, что использование адреса переменных таким образом переносимо. Хороший вопрос.

Ответ №1:

Я думаю, вы ищете что-то вроде:

 #include<stdio.h>

struct node { char *data; struct node *next; }
        b = {"data2", NULL}, a = {"data1", amp;b}, *root = amp;b;

int
main(void)
{
        printf("%sn", root->data);
        return 0;
}
 

или, может быть,:

 struct node { char *data; struct node *next; };
struct node *a = amp;(struct node){"data1", amp;(struct node){"data2", NULL}} ;

int
main(void)
{
        struct node *b = a->next;
        return 0;
}
 

Комментарии:

1. Я не уверен, что понимаю. Я изменил код; вы хотите сказать, что хотите struct node *root = amp;c ?

2. @OsourceAll отредактировал решение, чтобы, возможно, дать вам то, что вы хотите. Хотя это не совсем так.

3. Но я не понимаю, почему вы объявляете свой объект типами указателей, а не просто делаете: struct node { char *data; struct node *next; } b = {"data2", NULL}, a = {"data1", amp;b};

Ответ №2:

Если вы хотите статически инициализировать два разных указателя на один и тот же объект, вам необходимо назвать этот объект и использовать его адрес. Например:

 struct node {
    char *data;
    struct node *next;
};

char last_data[] = "last_data";
char* last_data_ptr = last_data;
struct node last_node = (struct node){last_data, NULL};
struct node* last_node_ptr = amp;last_node;
struct node* list = amp;(struct node){"first_data", amp;last_node};
 

Здесь amp;last_node используется дважды: один раз для инициализации last_node_ptr и один раз для инициализации поля в безымянной структуре, которое используется для инициализации list . Аналогично, last_data используется дважды, один раз для last_data_ptr и один раз для поля в last_node . Вы не можете сделать это с буквальным. Он может инициализировать только одну переменную.

Вот как можно создать циклический связанный список:

 struct node
{
    char* data;
    struct node* next;
} list = {"one", amp;(struct node){"two", amp;(struct node){"three", amp;list}}};
struct node *root = amp;list;
 

Комментарии:

1. «инициализировать корень до значения его следующего поля», похоже, не имеет для меня никакого смысла. Корень и его следующее поле-это две разные вещи. Если вы хотите иметь узел со следующим полем, указывающим на какой-либо «следующий» узел, и другим указателем с именем «корень», указывающим на тот же «следующий» узел, прочитайте ответ еще раз. Если вы хотите root быть указателем на указатель struct node и указывать на адрес поля какого-либо узла, то нет, это невозможно.

2. Если вам нужен круговой связанный список, почему бы не сказать, что вам нужен круговой связанный список прямо в вопросе?

3. Пример наличия адреса последнего узла был в ответе с самого начала. Ваши обновления не имеют для меня особого смысла, извините. Они пропускают статическую память и создают неинициализированные указатели.

4. struct node last_node = (struct node){last_data, NULL}; Оно есть и было там все время. Но это правда, что я понятия не имею, чего ты на самом деле хочешь.