Если у меня есть файл 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), он должен быть видимым. Самый худший способ сделать это - скопировать его в каждый исходный файл.
Правильный способ заключается в том, чтобы поместить его в заголовочный файл и включать этот заголовочный файл, когда это необходимо.
должен ли мы открыть новый файл заголовка и объявить структуру там и включить этот заголовок в 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 в файлы, где вы хотите использовать эту структуру.