两者都应该导致相同的可用性,即使是通过链接实现的,不是吗?
不,当您考虑其他具有相同头文件的.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
$
因此,“实施中的定义”版本可防止意外或故意滥用私有实施细节。