если эта структура будет использоваться другим файлом 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:
Крейг Барнс напоминает нам в своем комментарии, что вам не нужно хранить отдельные имена для имени struct "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 для структур и других символов. ,
struct b
, но тогда ваша структураa
объявляет тип, который не используется (вероятно, вам следует определить имя члена, возможноk
, после внутренней закрывающей скобки и перед точкой с запятой