Как объявить структуру в заголовке, который должен использоваться несколькими файлами в c?

Если у меня есть файл 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 в файлы, где вы хотите использовать эту структуру.