दोनों को एक ही प्रयोज्य में परिणत करना चाहिए, भले ही एक लिंकेज के द्वारा हो, क्या उन्हें नहीं करना चाहिए?
नहीं, नहीं जब आप एक ही हेडर सहित अन्य .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; |
| } |
+---------------------------------+
एपीआई का यह क्लाइंट या तो संस्करण के साथ काम करता है:
#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
$
तो, "कार्यान्वयन में परिभाषा" संस्करण निजी कार्यान्वयन विवरणों के आकस्मिक या जानबूझकर दुरुपयोग से बचाता है।