Ambos deberían resultar en la misma usabilidad, incluso si uno es por enlace, ¿no es así?
No, no cuando considera otros archivos .c que incluyen el mismo encabezado. Si la definición de la estructura no es visible para el compilador, los detalles de esa definición no se pueden utilizar. Una declaración sin una definición (por ejemplo, simplemente struct s;
) hace que el compilador falle si algo intenta mirar dentro struct s
, mientras que aún le permite, por ejemplo, compilar struct s *foo;
(siempre que foo
no se desreferencia más tarde).
Compare estas versiones 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; |
| } |
+---------------------------------+
Este cliente de la API funciona con cualquiera de las versiones:
#include "api.h"
void good(struct s *foo)
{
api_func(foo, 123);
}
Este hurga en los detalles de implementación:
#include "api.h"
void bad(struct s *foo)
{
foo->internal = 123;
}
que funcionará con la versión "definición en encabezado", pero no con la versión "definición en implementación", ya que en el último caso el compilador no tiene visibilidad del diseño de la estructura:
$ gcc -Wall -c bad.c
bad.c: In function 'bad':
bad.c:5: error: dereferencing pointer to incomplete type
$
Por lo tanto, la versión de "definición en implementación" protege contra el uso indebido accidental o deliberado de detalles de implementación privados.