135 votes

Les définitions de structures doivent-elles être placées dans le fichier .h ou .c ?

J'ai vu les deux définitions complètes de struct dans les en-têtes et les simples déclarations - y a-t-il un avantage à utiliser une méthode plutôt qu'une autre ?

Si cela peut faire une différence, j'ai l'habitude de typifier une structure comme suit dans la section .h

typedef struct s s_t;

Pour être clair, les options sont la déclaration dans le fichier d'en-tête et la définition dans la classe, ou à la fois la déclaration et la définition dans le fichier d'en-tête. Les deux devraient aboutir à la même facilité d'utilisation, même si l'une d'entre elles est liée à la classe, n'est-ce pas ?


Je vois de nombreux doublons, par exemple aquí mais pas de correspondance exacte. Veuillez me corriger si je me trompe à cet égard.

138voto

τεκ Points 1251

Les structures privées de ce fichier doivent être placées dans le fichier .c, avec une déclaration dans le fichier .h si elles sont utilisées par des fonctions du fichier .h .

Les structures publiques doivent être placées dans le fichier .h.

86voto

Matthew Slattery Points 21628

Les deux devraient aboutir à la même facilité d'utilisation, même si l'une d'entre elles est liée à l'autre, n'est-ce pas ?

Non, pas si l'on considère que d'autres fichiers .c contiennent le même en-tête. Si la définition de la structure n'est pas visible pour le compilateur, les détails de cette définition ne peuvent pas être utilisés. Une déclaration sans définition (par exemple juste struct s; ) fait échouer le compilateur si quelque chose essaie de regarder à l'intérieur de struct s tout en lui permettant, par exemple, de compiler struct s *foo; (pour autant que foo n'est pas déréférencé ultérieurement).

Comparez ces versions de api.h y 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;          |
                                      | }                               |
                                      +---------------------------------+

Ce client de l'API fonctionne avec l'une ou l'autre version :

#include "api.h"

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

Celui-ci se penche sur les détails de la mise en œuvre :

#include "api.h"

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

qui fonctionnera avec la version "définition dans l'en-tête", mais pas avec la version "définition dans l'implémentation", car dans ce dernier cas, le compilateur n'a aucune visibilité sur l'agencement de la structure :

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

Ainsi, la version "définition dans l'implémentation" protège contre l'utilisation accidentelle ou délibérée de détails d'implémentation privés.

10voto

nos Points 102226

Si la structure doit être utilisée par d'autres unités de compilation (fichiers .c), placez-la dans le fichier d'en-tête afin de pouvoir inclure ce fichier d'en-tête partout où il est nécessaire.

Si la structure n'est utilisée que dans une seule unité de compilation (fichier .c), vous la placez dans ce fichier .c.

5voto

Jonathan Wood Points 26443

Le fait de la placer dans un fichier d'en-tête vous permet d'utiliser la structure (ou toute autre définition) à partir de plusieurs fichiers sources, simplement en incluant ce fichier d'en-tête.

Mais si vous êtes sûr qu'il ne sera utilisé qu'à partir d'un seul fichier source, cela ne fait aucune différence.

1voto

TofuBeer Points 32441

Je les ai placés dans le fichier C pour le rendre plus orienté objet, voir cet article .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X