якщо цю структуру повинен використовувати якийсь інший файл 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 ++), тому я не буду деталізувати.
то як оголосити цю структуру як зовнішню в обох файлах. ?
Я не бачу сенсу, можливо, але Грег Х'югілл має дуже хорошу відповідь у своєму дописі Як оголосити структуру в заголовку, який повинен використовуватися декількома файлами в c? .
чи введемо це тоді, як?
- Якщо ви використовуєте C ++, не робіть цього.
- Якщо ви використовуєте C, ви повинні.
Причиною цього є те, що керування структурою C може викликати біль: Ви повинні оголосити ключове слово Stru всюди, де воно використовується:
struct MyStruct ; /* Forward declaration */
struct MyStruct
{
/* etc. */
} ;
void doSomething(struct MyStruct * p) /* parameter */
{
struct MyStruct a ; /* variable */
/* etc */
}
Хоча typedef дозволить вам записати його без ключового слова stru.
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 скрізь, де вам захочеться уникати додавання ключового слова stru, і все одно використовувати MyStructTag, коли typedef не працюватиме (тобто переадресація)
Редагувати:
Виправлено неправильне припущення щодо декларації структури С99, як справедливо зауважив Джонатан Леффлер .
Редагувати 2018-06-01:
Крейг Барнс нагадує нам у своєму коментарі, що вам не потрібно зберігати окремі назви для структури "тег" імені та його "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
, після внутрішнього закриття дужки та перед крапкою з комою.