Вопрос:
Если у меня есть файл source.c со структурой:
struct a { int i; struct b { int j; } };
Как эта структура может использоваться в другом файле (т.е. func.c)?
Должен ли я создать новый заголовочный файл, объявить структуру там и включить этот заголовок в func.c?
Или я должен определить всю структуру в файле заголовка и включить ее как в source.c, так и в func.c? Как можно объявить структуру extern в обоих файлах?
Должен ли я typedef это? Если да, то как?
Ответ №1Содержание
- , если эта структура должна использоваться каким-либо другим файлом func.c, как это сделать?
- должен ли мы открыть новый файл заголовка и объявить структуру там и включить этот заголовок в func.c?
- или мы можем определить общую структуру в заголовочном файле и включить это как в source.c, так и в func.c?
- , то как объявить эту структуру как extern в обоих файлах.
- , мы должны ввести его тогда, как?
- Edit:
- , если эта структура должна использоваться каким-либо другим файлом func.c, как это сделать?
- должен ли мы открыть новый файл заголовка и объявить структуру там и включить этот заголовок в func.c?
- или мы можем определить общую структуру в заголовочном файле и включить это как в source.c, так и в func.c?
- , то как объявить эту структуру как extern в обоих файлах.
- , мы должны ввести его тогда, как?
- Edit:
, если эта структура должна использоваться каким-либо другим файлом func.c, как это сделать?
Когда тип используется в файле (т.е. файл func.c), он должен быть видимым. Самый худший способ сделать это – скопировать его в каждый исходный файл.
Правильный способ заключается в том, чтобы поместить его в заголовочный файл и включать этот заголовочный файл, когда это необходимо.
должен ли мы открыть новый файл заголовка и объявить структуру там и включить этот заголовок в func.c?
Это решение, которое мне больше нравится, потому что он делает код очень модульным. Я бы назвал вашу структуру следующим:
#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME #define SOME_HEADER_GUARD_WITH_UNIQUE_NAME struct a { int i; struct b { int j; } }; #endif
Я бы поставил функции, используя эту структуру в том же заголовке (функция, которая является “семантически” частью своего “интерфейса” ).
И, как правило, я могу назвать файл после имени структуры и снова использовать это имя для выбора параметров защиты заголовков.
Если вам нужно объявить функцию с помощью указателя на структуру, вам не понадобится полное определение структуры. Простое форвардное объявление вроде:
struct a ;
Будет достаточно, и это уменьшит связь.
или мы можем определить общую структуру в заголовочном файле и включить это как в source.c, так и в func.c?
Это еще один способ, более простой, но менее модульный. Некоторый код, требующий только вашей структуры для работы, все равно должен включать все типы.
В С++ это может привести к интересному усложнению, но это не в тему (нет тега С++), поэтому я не буду подробно останавливаться.
, то как объявить эту структуру как extern в обоих файлах.
Я не вижу смысла, возможно, но Грег Хьюджилл имеет очень хороший ответ в своем посте Как объявить структуру в заголовке, который должен использоваться несколькими файлами в с?.
, мы должны ввести его тогда, как?
- Если вы используете С++, не делайте этого.
- Если вы используете C, вы должны.
Причина в том, что управление структурой C может быть болью: вы должны объявить ключевое слово struct везде, где оно используется:
struct MyStruct ; /* Forward declaration */ struct MyStruct { /* etc. */ } ; void doSomething(struct MyStruct * p) /* parameter */ { struct MyStruct a ; /* variable */ /* etc */ }
В то время как typedef позволит вам записать его без ключевого слова struct.
struct MyStructTag ; /* Forward declaration */ typedef struct MyStructTag { /* etc. */ } MyStruct ; void doSomething(MyStruct * p) /* parameter */ { MyStruct a ; /* variable */ /* etc */ }
важно, вы все равно сохраняете имя для структуры. Запись:
typedef struct { /* etc. */ } MyStruct ;
просто создаст анонимную структуру с именем typedef-ed, и вы не сможете ее переадресовать. Итак, держись в следующем формате:
typedef struct MyStructTag { /* etc. */ } MyStruct ;
Таким образом, вы сможете использовать MyStruct везде, где хотите избежать добавления ключевого слова struct, и по-прежнему использовать MyStructTag, когда typedef не будет работать (т.е. форвардное объявление)
Edit:
Исправлено неверное предположение о декларации структуры C99, как справедливо заметил Джонатан Леффлер.
Ответ №2
Для определения структуры, которое должно использоваться в более чем одном исходном файле, вы должны обязательно поместить его в файл заголовка. Затем включите этот заголовочный файл в любой исходный файл, который нуждается в структуре.
Объявление extern не используется для определения структуры, но вместо этого используется для объявлений переменных (то есть, для некоторого значения данных с указанным типом структуры). Если вы хотите использовать одну и ту же переменную в нескольких исходных файлах, объявите ее как extern в заголовочном файле, например:
extern struct a myAValue;
Затем в одном исходном файле определите действительную переменную:
struct a myAValue;
Если вы забыли сделать это или случайно определить его в двух исходных файлах, компоновщик сообщит вам об этом.
Ответ №3
хиджры:
#ifndef A_H #define A_H struct a { int i; struct b { int j; } }; #endif
там вы идете, теперь вам просто нужно включить a.h в файлы, где вы хотите использовать эту структуру.