если эта структура будет использоваться другим файлом 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?
Это другой способ, несколько проще, но менее модульный: некоторый код, которому для работы нужна только ваша структура, все равно должен включать все типы.
В C ++ это может привести к интересным осложнениям, но это не по теме (без тега C ++), поэтому я не буду вдаваться в подробности.
затем как объявить эту структуру как extern в обоих файлах. ?
Возможно, я не понимаю сути, но у Грега Хьюгилла есть очень хороший ответ в своем сообщении Как объявить структуру в заголовке, которая будет использоваться несколькими файлами в c?.
тогда как мы его наберем?
- Если вы используете C ++, не делайте этого.
- Если вы используете 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 struct MyStructTag
{
/* etc. */
} MyStruct ;
Таким образом, вы сможете использовать MyStruct везде, где хотите избежать добавления ключевого слова struct, и по-прежнему использовать MyStructTag, когда typedef не работает (например, предварительное объявление)
Редактировать:
Исправлено неправильное предположение об объявлении структуры C99, как справедливо заметил Джонатан Леффлер.
Изменить 2018-06-01:
Крейг Барнс напоминает нам в своем комментарии, что вам не нужно хранить отдельные имена для имени структурного тега и его typedef name, как я сделал выше для ясности.
Действительно, приведенный выше код можно было бы записать как:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC, на самом деле это то, что C ++ делает с его более простым объявлением структуры за кулисами, чтобы поддерживать его совместимость с C:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
Возвращаясь к C, я видел оба использования (разные имена и одинаковые имена), и ни у одного из них нет недостатков, о которых я знаю, поэтому использование одного и того же имени упрощает чтение, если вы не используете C отдельные пространства имен для структур и других символов.
person
paercebal
schedule
23.10.2008
struct b
, но тогда ваша структураa
объявляет неиспользуемый тип (вам, вероятно, следует определить имя члена, возможноk
, после внутреннего закрывающая фигурная скобка и перед точкой с запятой. - person Jonathan Leffler   schedule 01.10.2014