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.