Entrambi dovrebbero portare alla stessa usabilità, anche se uno è per collegamento, no?
No, non quando si considerano altri file .c che includono la stessa intestazione. Se la definizione della struttura non è visibile al compilatore, i dettagli di quella definizione non possono essere utilizzati. Una dichiarazione senza una definizione (ad esempio solo struct s;
) fa sì che il compilatore fallisca se qualcosa cerca di guardare all'interno struct s
, pur permettendogli di ad esempio di compilare struct s *foo;
(purché foo
non venga successivamente dereferenziato).
Confronta queste versioni di api.h
e 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; |
| } |
+---------------------------------+
Questo client dell'API funziona con entrambe le versioni:
#include "api.h"
void good(struct s *foo)
{
api_func(foo, 123);
}
Questo fa un giro nei dettagli di implementazione:
#include "api.h"
void bad(struct s *foo)
{
foo->internal = 123;
}
che funzionerà con la versione "definizione in intestazione", ma non con la versione "definizione in implementazione", in quanto in quest'ultimo caso il compilatore non ha visibilità del layout della struttura:
$ gcc -Wall -c bad.c
bad.c: In function 'bad':
bad.c:5: error: dereferencing pointer to incomplete type
$
Quindi, la versione "definizione nell'implementazione" protegge dall'uso improprio accidentale o intenzionale dei dettagli dell'implementazione privata.