Можно ли получить указатель на структуру this при использовании назначенного инициализатора? - PullRequest
6 голосов
/ 23 августа 2011

Этот вид структуры используется в качестве заголовка связанного списка:

struct lista
{
    struct lista* next;
    struct lista* prev;
};

Когда next и prev оба указывают на структурирование, список пуст. Следующий макрос можно использовать для инициализации структуры:

#define LISTA_INIT_EMPTY(list) { .next = (list), .prev = (list) }

таким образом:

struct lista my_list = LISTA_INIT_EMPTY(&my_list);

Но есть ли способ сделать то же самое следующим образом без макропараметра?

struct lista my_list = LISTA_INIT_EMPTY;

Я попробовал следующее, но это вызвало ошибку компиляции:

#define LISTA_INIT_EMPTY     { .next = &.next, .prev = &.next }

Ответы [ 5 ]

6 голосов
/ 23 августа 2011

Ну, единственный способ, который я вижу, неприятен:

#define LISTA_INIT_EMPTY     { .next = (&my_list), .prev = (&my_list) }

Совсем не приятно, так как работает, только если ваша переменная называется my_list.И нет хорошего способа, поскольку this не существует в C.

Почему бы не использовать NULL вместо указания на "this"?Если это неудовлетворительно, лучше всего сохранить параметризованный макрос.

РЕДАКТИРОВАТЬ: (благодаря комментарию R ниже, я наконец понял необходимость):

Какздесь нет «this», и чтобы ввести имя переменной только один раз, я предлагаю использовать такой макрос:

#define CREATE_EMPTY_LISTA(name) struct lista name = { .next=&name, .prev=&name }

А позже в коде:

CREATE_EMPTY_LISTA(my_list); // creates and initializez my_list at the same time
2 голосов
/ 23 августа 2011

Обратите внимание, что ваш метод инициализации списков аналогичен тому, который используется в исходном коде ядра Linux для их связанных списков (include/linux/list.h).

Для инициализации списка при объявлении заголовка списка, вместо попытки сделать что-то вроде:

// won't work:
struct lista my_list = /* something or other */;

В Linux используется макрос, который выполняет и делкарацию, и инициализацию (поэтому пользователю все равно придется использовать имя только один раз). Для вашего struct lista это может выглядеть так:

#define LISTA_HEAD struct lista name = LISTA_INIT_EMPTY(name)

// this is all the user needs to do to both declare and initialize a list:
LISTA_HEAD(my_list);

Взгляните на include/linux/list.h для всех деталей. Есть также хорошие объяснения того, как работают списки (не все из них интуитивно понятны):

0 голосов
/ 23 августа 2011

Нет, ваш инициализатор создает struct lista, а затем назначает my_list.Ваша идея this не имеет смысла в этом контексте, она не будет указывать на my_list до тех пор, пока она не будет назначена.

0 голосов
/ 23 августа 2011

Очевидно, что это невозможно, поскольку блок должен знать экземпляр.

Также .next = &.next не будет работать, так как типы не совпадают.(struct lista* до struct lista**)

0 голосов
/ 23 августа 2011

Не совсем!Если вы определили пустой как NULL вместо «себя», то вы можете сделать это следующим образом:

#define LISTA_INIT_EMPTY {NULL,NULL}

...