C: указатель на структуру в определении структуры

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

typedef struct A {
  int a;
  int b;
  A*  next;
} A;

так я написал это вначале, но это не работает.


person claf    schedule 03.02.2009    source источник
comment
Примечание C11 §6.7.2.1 Спецификаторы структуры и объединения ¶3: Структура или объединение не должны содержать члена с неполным или функциональным типом (следовательно, структура не должна содержать своего экземпляра, но может содержать указатель на свой экземпляр),…   -  person Jonathan Leffler    schedule 14.11.2019


Ответы (7)


Вы можете определить typedef и сначала объявить структуру в одном операторе, а затем определить структуру в последующем определении.

typedef struct A A;

struct A
{
    int a;
    int b;
    A* next;
};

Изменить: как уже упоминалось, без предварительного объявления имя структуры все еще действует внутри определения структуры (т.е. вы можете использовать struct A), но typedef недоступен до тех пор, пока определение typedef не будет завершено (поэтому использование только A не быть действительным). Это может не иметь большого значения для всего лишь одного члена-указателя, но если у вас сложная структура данных с большим количеством указателей собственного типа, это может быть менее удобным.

person CB Bailey    schedule 03.02.2009
comment
Это канонический способ сделать это. - person unwind; 03.02.2009
comment
раскрутка: многие соглашения о стилях кодирования для C категорически против структур определения типов. Я бы не сказал, что это вообще канонично. - person Chris Young; 03.02.2009
comment
Если бы я мог проголосовать за комментарии, Крис Янг получил бы +1. Между собственными типами и агрегатными структурами существует огромная разница. Не скрывайте это за typedef. - person ephemient; 04.02.2009
comment
@ephemient: Теперь ты можешь. - person Keith Thompson; 28.05.2014
comment
@ephemient Почему мне не скрывать это? Это просто детали реализации. - person YoTengoUnLCD; 26.02.2017
comment
Почему в typedef struct A A две буквы «А»; ? - person turner; 01.12.2017
comment
@turner: потому что один A определяет тип структуры в struct A, а второй дает типу имя (псевдоним) A. Если у вас было typedef int B;, то int - это тип, а B - новое имя для типа. Таким же образом с typedef struct A A;, struct A - это тип, а A - новое имя для типа. - person Jonathan Leffler; 14.11.2019

В дополнение к первому ответу, без объявления typedef и forward, это тоже должно быть хорошо.

struct A 
{ 
    int a; 
    int b; 
    struct A *next; 
};
person Chris Young    schedule 03.02.2009
comment
Плюс без typedef вы действительно знаете, имеете ли вы дело со структурой в коде - person Greg Schmit; 27.08.2018

Вам не хватает struct перед A*

  typedef struct A {
    int a;
    int b;
    struct A* next;
  } A;
person Miles D    schedule 03.02.2009

Вы можете обойтись без форвардного объявления:

struct A {
    int a;
    int b;
    struct A *next;
};
person qrdl    schedule 03.02.2009

Пожалуйста, вы используете C, а не C ++.

Если вам действительно нужно typedef структуры (а большинство программистов, с которыми я работаю, не станут), сделайте следующее:

typedef struct _A {
    int a;
    int b;
    struct _A *next;
} A;

чтобы четко различать _A (в пространстве имен struct) и A (в пространстве имен типа).

¹typedef скрывает размер и хранилище типа, на который указывает - аргумент (и я согласен) заключается в том, что на низкоуровневом языке, таком как C, попытки скрыть что-либо вредны и контрпродуктивны. Привыкайте набирать struct A всякий раз, когда вы имеете в виду struct A.

person ephemient    schedule 03.02.2009
comment
Как структура A сообщает мне что-нибудь о своем размере? - person quant_dev; 04.02.2009
comment
Он сообщает вам, что это агрегированная структура, и поэтому многие вещи, такие как передача ее в качестве аргументов, ее возврат, сравнения и a = b, неэффективны или не будут работать. - person ephemient; 04.02.2009
comment
A - зарезервированное имя. A было бы хорошо. - person MSalters; 12.02.2009
comment
Nitpick: _A - плохая репутация: начальные подчеркивания принадлежат компилятору. edit Черт, думаю, я только что повторил MSalters. - person Bernd Jendrissek; 18.06.2010
comment
За все время своего программирования я никогда не сталкивался с проблемой присвоения структуре и typedef одного и того же имени, а затем я только удосужился дать структуре имя в этом точном случае (связанные списки и т. Д.). Я думаю, вы просто продвигаете FUD. Можете ли вы привести пример, в котором возникают проблемы, чтобы дать одно и то же имя обоим? Кроме того, я никогда не сталкивался с какой-либо проблемой при использовании typedef во всех моих структурах, поэтому я считаю, что ваш аргумент о том, что слишком «вредно и контрпродуктивно» - быть чрезмерным. - person Wayne Uroda; 21.06.2018
comment
Обратите внимание, что _A в struct _A находится в пространстве имен «тег»; A в конце typedef находится в пространстве имен «обычные идентификаторы» (совместно с именами переменных, именами функций, именами типов и т. д.). Если существует пространство имен структуры, это означает набор имен членов структуры (и каждая структура или тип объединения имеет свое собственное пространство имен). См. C11 §6.2.3 Пространства имен идентификаторов. - person Jonathan Leffler; 13.10.2018
comment
Обратите внимание, что, как правило, не следует создавать имена функций, переменных, тегов или макросов, начинающиеся с подчеркивания. В части C11 §7.1.3 Зарезервированные идентификаторы говорится: - Все идентификаторы, которые начинаются с подчеркивания и либо прописной буквы, либо другого подчеркивания, всегда зарезервированы для любого использования. - Все идентификаторы, начинающиеся с подчеркивания, всегда зарезервированы для использования в качестве идентификаторов с файлом область видимости как в обычном пространстве имен, так и в пространстве имен тегов. См. также Что означает двойное подчеркивание (__const) в C? - person Jonathan Leffler; 13.10.2018

typedef struct {
 values
} NAME;

Это более короткий способ typedef структуры, я думаю, что это самая простая нотация, просто не помещайте имя спереди, а позади.

тогда вы можете назвать это как

NAME n;  

NAME *n; // if you'd like a ptr to it.

Что-то не так с этим подходом?

person user7296055    schedule 14.12.2016
comment
как указано в вопросе, необходимо иметь указатель ВНУТРИ структуры (связанный список), поэтому я не вижу, что ваш ответ добавляет сюда. - person claf; 10.01.2017

Используйте следующий препроцессор:

#define structdef(NAME) typedef struct NAME NAME; struct NAME 

Использование:

structdef(node_t)
{
   void* value;
   node_t* next;
};
person moien    schedule 21.01.2019