উভয়ের একই ব্যবহারের ফলস্বরূপ হওয়া উচিত, এমনকি যদি কোনও যোগসূত্র দ্বারা হয় তবে তাদের উচিত নয়?
না, যখন আপনি একই শিরোনাম সহ অন্যান্য .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
$
সুতরাং, "বাস্তবায়নের সংজ্ঞা" সংস্করণটি দুর্ঘটনাজনিত বা ব্যক্তিগত প্রয়োগের বিশদগুলির ইচ্ছাকৃত অপব্যবহারের বিরুদ্ধে সুরক্ষা দেয়।