если эта структура будет использоваться другим файлом 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-ed, и вы не сможете его предварительно объявить. Поэтому придерживайтесь следующего формата:
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
Таким образом, вы сможете использовать MyStruct везде, где хотите избежать добавления ключевого слова struct, и по-прежнему использовать MyStructTag, когда typedef не будет работать (т.е. прямое объявление)
Edit:
Исправлено неверное предположение о объявлении структуры C99, как справедливо заметил Джонатан Леффлер .
Редактировать 2018-06-01:
Крейг Барнс напоминает нам в своем комментарии, что вам не нужно хранить отдельные имена для имени структуры "tag" и его имени "typedef", как я делал выше для ясности.
Действительно, приведенный выше код вполне можно записать так:
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 отдельных "пространств имен "для структур и других символов .