Должны ли определения структуры идти в файле .h или .c? - PullRequest
90 голосов
/ 11 июня 2011

Я видел как полные определения struct s в заголовках, так и просто объявления - есть ли преимущество одного метода перед другим?

Если это имеет значение, я обычно печатаю определение структуры, напримерпоэтому в .h

typedef struct s s_t;

Редактировать

Для ясности, опции - это объявление в заголовочном файле и определение в классе, или объявление и определение взаголовочный файлИ то, и другое должно привести к одинаковому удобству использования, даже если один связан, не так ли?


Я вижу много почти дубликатов, например, здесь , но точных совпадений нет.Пожалуйста, поправьте меня, если я ошибаюсь в этом отношении.

Ответы [ 6 ]

92 голосов
/ 11 июня 2011

Частные структуры для этого файла должны быть в файле .c с объявлением в файле .h, если они используются какими-либо функциями в .h.

Открытые структуры должны идти в .hфайл.

65 голосов
/ 11 июня 2011

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

Нет, если вы рассматриваете другие файлы .c, включающие один и тот же заголовок.Если определение структуры не видно компилятору, детали этого определения не могут быть использованы.Объявление без определения (например, просто struct s;) приводит к сбою компилятора, если что-либо пытается заглянуть внутрь struct s, и в то же время позволяет ему, например, скомпилировать struct s *foo; (пока foo не будет позднее разыменовано).

Сравните эти версии api.h и api.c:

Definition in header:                 Definition in implementation:
+---------------------------------+   +---------------------------------+
| struct s {                      |   | struct s;                       |
|     int internal;               |   |                                 |
|     int other_stuff;            |   | extern void                     |
| };                              |   | api_func(struct s *foo, int x); |
|                                 |   +---------------------------------+
| extern void                     |   +---------------------------------+
| api_func(struct s *foo, int x); |   | #include "api.h"                |
+---------------------------------+   |                                 |
+---------------------------------+   | struct s {                      |
| #include "api.h"                |   |     int internal;               |
|                                 |   |     int other_stuff;            |
| void                            |   | };                              |
| api_func(struct s *foo, int x)  |   |                                 |
| {                               |   | void                            |
|     foo->internal = x;          |   | api_func(struct s *foo, int x)  |
| }                               |   | {                               |
+---------------------------------+   |     foo->internal = x;          |
                                      | }                               |
                                      +---------------------------------+

Этот клиент API работает с любой из версий:

#include "api.h"

void good(struct s *foo)
{
    api_func(foo, 123);
}

В этой версиив деталях реализации:

#include "api.h"

void bad(struct s *foo)
{
    foo->internal = 123;
}

, который будет работать с версией «определения в заголовке», но не с версией «определения в реализации», так как в последнем случае компилятор не имеет видимости макетаструктуры:

$ gcc -Wall -c bad.c
bad.c: In function 'bad':
bad.c:5: error: dereferencing pointer to incomplete type
$

Таким образом, версия «определение в реализации» защищает от случайного или преднамеренного неправильного использования подробностей частной реализации.

7 голосов
/ 11 июня 2011

Если структура будет использоваться другими модулями компиляции (файлы .c), поместите ее в файл заголовка, чтобы вы могли включить этот файл заголовка, где бы он ни понадобился.

Если структура используется только в одном модуле компиляции (файл .c), вы помещаете ее в этот файл .c.

3 голосов
/ 11 июня 2011

Дело в том, что размещение его в заголовочном файле позволяет вам использовать структуру (или любое другое определение) из нескольких исходных файлов, просто включив этот заголовочный файл.

Но если вы уверены, что это будетиспользовать только из одного исходного файла, тогда это действительно не имеет никакого значения.

0 голосов
/ 11 июня 2011

Вообще, я не думаю, что это имеет огромное значение, помещаете ли вы их в заголовок или исходные файлы. Однако если вам нужен доступ к элементам структуры из нескольких исходных файлов, проще поместить структуру в заголовочный файл и включить ее из любых других файлов, где требуется структура.

0 голосов
/ 11 июня 2011

Я поместил их в файл C, чтобы сделать его более объектно-ориентированным, см. Эту статью .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...