Cả hai sẽ dẫn đến khả năng sử dụng giống nhau, ngay cả khi một là do liên kết, phải không?
Không, không phải khi bạn xem xét các tệp .c khác bao gồm cùng một tiêu đề. Nếu định nghĩa của cấu trúc không hiển thị cho trình biên dịch, thì không thể sử dụng chi tiết của định nghĩa đó. Một khai báo không có định nghĩa (ví dụ: chỉ struct s;
) khiến trình biên dịch không thành công nếu có bất kỳ thứ gì cố gắng tìm kiếm bên trong struct s
, trong khi vẫn cho phép nó biên dịch, ví dụ struct s *foo;
như foo
sau này không được tham chiếu đến).
So sánh các phiên bản này của api.h
và 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; |
| } |
+---------------------------------+
Ứng dụng khách này của API hoạt động với một trong hai phiên bản:
#include "api.h"
void good(struct s *foo)
{
api_func(foo, 123);
}
Cái này xoay quanh chi tiết triển khai:
#include "api.h"
void bad(struct s *foo)
{
foo->internal = 123;
}
sẽ hoạt động với phiên bản "định nghĩa trong tiêu đề", nhưng không hoạt động với phiên bản "định nghĩa trong triển khai", như trong trường hợp sau, trình biên dịch không hiển thị được bố cục của cấu trúc:
$ gcc -Wall -c bad.c
bad.c: In function 'bad':
bad.c:5: error: dereferencing pointer to incomplete type
$
Vì vậy, phiên bản "định nghĩa trong triển khai" bảo vệ chống lại việc sử dụng sai một cách vô tình hoặc cố ý các chi tiết triển khai riêng tư.