Объявление структуры: имя структуры typedef;

мы все знаем, как объявить структуру в C:

struct Label1{ /* variables */ } Label2; // As I learned

но я хочу знать, почему этот код работает без объявления 'struct name':

typedef struct name s_name;

или на самом деле, набирает код

struct name;

означает, что я объявил "имя структуры" как пустотную структуру или что-то в этом роде?

пример кода:

typedef struct Data Data;
struct Data{ /*variables*/ };

если в первой строке данные структуры объявлены как пустые, то во второй это похоже на то, что я объявляю его с членами.

каково объяснение этого момента?

2 ответов


что-то типа:

struct MyStruct;

называется прямой ссылкой. Он создает неполный тип и сообщает компилятору, что будет тип этого имени (и это структура - она также работает для Союзов), а детали "следуют позже". Такого типа вы не можете определить переменные, пока не завершите тип.

typedef struct MyStruct MyType;

просто определит имя типа, которое будет этой структурой. Это все еще неполный тип.

тем не менее, вы можете взять указатель на неполный тип:

MyType *my_t_pointer;
struct MyStruct *my_s_pointer;

это полезно для структуры, чтобы иметь указатели на объекты того же типа, когда вы предоставляете полное объявление, "завершая" тип:

struct MyStruct {
    struct MyStruct *next;
};

на самом деле это единственный способ создания узлов для списков, деревьев и всех других рекурсивных структур данных. Это основная часть c-программ (иногда скрытых).

кроме того, этот механизм используется для скрытия деталей реализации. Функции в заголовке должны знать только структуру существует, чтобы взять/передать указатели на него. Использование этих функций не должно знать деталей структуры (но таким образом он не может ее выделить, поэтому модуль должен охватывать все аспекты, которые должны знать детали структуры). Полное объявление находится только внутри файла реализации модуля. Эти указатели называются "непрозрачными", поскольку невозможно" просмотреть", т. е. получить доступ к полям структуры, поскольку они ей просто не известны.

мой_модуль.h:

struct MyStruct;

extern void my_init(struct MyStruct *obj);

мой_модуль.c:

struct MyStruct {
    int f1;
    ...
};

my_init(struct MyStruct *obj)
{
    ...
}

typedef объявляет s_name как псевдоним для имени структуры, чтобы вы могли объявлять переменные, например:

s_name *sptr;

строку

struct name;

объявляет, что существует тип структуры с именем name без определения его содержимого. Обычно это делается для того, чтобы иметь возможность объявлять переменные как указатели на тип struct. Вы не можете объявлять переменные фактического типа структуры, пока он не будет определен.