क्या संरचना की परिभाषाएँ .h या .c फ़ाइल में जानी चाहिए?


102

मैंने structहेडर में दोनों की पूर्ण परिभाषाएँ देखी हैं और सिर्फ घोषणाएँ की हैं - क्या किसी एक विधि का दूसरे पर कोई लाभ है?

अगर इससे कोई फर्क पड़ता है, तो मैं आमतौर पर एक संरचना टाइप करता हूं जैसे कि .h

typedef struct s s_t;

संपादित करें

स्पष्ट होने के लिए, शीर्ष लेख फ़ाइल में विकल्प की घोषणा की जाती है और वर्ग में परिभाषा, या शीर्षक फ़ाइल में घोषणा और परिभाषा दोनों होती है। दोनों को एक ही प्रयोज्य में परिणत करना चाहिए, भले ही एक लिंकेज के द्वारा हो, क्या उन्हें नहीं करना चाहिए?


मैं कई लगभग डुप्लिकेट देखता हूं, जैसे यहां लेकिन कोई सटीक मिलान नहीं। कृपया इस संबंध में गलत होने पर मुझे सही करें।


2
क्या आप एक अपारदर्शी या गैर-अपारदर्शी संरचना चाहते हैं?

4
साइड नोट, पहचानकर्ता _tPOSIX द्वारा आरक्षित हैं, इसलिए यह आमतौर पर एक बुरा विचार है। आप बस कर सकते हैं typedef struct toto toto
जेन्स गुस्ताद

मैंने _tअन्य स्थानों (जैसे, लाइटटैप, लिनक्स) का बहुत उपयोग किया है ... और मैंने projident_ के साथ चीजों को उपसर्ग किया है, इसलिए यह एक मुद्दा नहीं होना चाहिए?
हारून योडिकेन

और @WTP, मुझे लगता है कि गैर-अपारदर्शी आमतौर पर बेहतर और अधिक Cईश माना जाता है , नहीं ( FILEउदाहरण के साथ क्या है )। तो, गैर अपारदर्शी।
एरोन योदिकेन

यदि यह एक गैर-अपारदर्शी संरचना है, तो इसे हेडर फ़ाइल में जाना होगा, या आपका कोड DRY नहीं है (अपने आप को दोहराएं नहीं)।

जवाबों:


107

उस फ़ाइल के लिए निजी संरचनाओं को .h फ़ाइल में जाना चाहिए। .h फ़ाइल में एक घोषणा के साथ यदि वे .h फ़ाइल में उनके कार्यों द्वारा उपयोग की जाती हैं।

सार्वजनिक संरचनाओं को .h फ़ाइल में जाना चाहिए।


4
मुझे लगता है कि मैं इस जवाब से अधिक सहमत हूं। यह किसी अन्य .c फ़ाइलों के माध्यम से संरचना का उपयोग करने के बारे में नहीं है या नहीं, यह है कि क्या संरचना को सार्वजनिक (और इसलिए, सुलभ) माना जाना चाहिए या नहीं।
c00kiemon5ter

@ τεκ क्या आपका मतलब globalऔर localदृश्यता है? publicएक संरचना में समझ में नहीं आता है। सभी संरचनाएं डिफ़ॉल्ट रूप से सार्वजनिक हैं।
BugShotGG 16

3
@Geo Papas यह C. के बारे में एक प्रश्न है। C. publicमें कोई कीवर्ड नहीं है। यदि आप मैथ्यू स्लटर के उत्तर को देखते हैं, तो आप देख सकते हैं कि हेडर में केवल आगे की घोषणा का उपयोग करने से कंपाइलर त्रुटि होती है, जब उपयोगकर्ता किसी सदस्य के सदस्यों का उपयोग करने का प्रयास करता है निजी (अपारदर्शी) संरचना।
τεκ

68

दोनों को एक ही प्रयोज्य में परिणत करना चाहिए, भले ही एक लिंकेज के द्वारा हो, क्या उन्हें नहीं करना चाहिए?

नहीं, नहीं जब आप एक ही हेडर सहित अन्य .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
$

तो, "कार्यान्वयन में परिभाषा" संस्करण निजी कार्यान्वयन विवरणों के आकस्मिक या जानबूझकर दुरुपयोग से बचाता है।


3
बस जानना चाहते हैं कि आपने उन कोड विंडो को कैसे बनाया और अभी भी उनके अंदर कोड हाइलाइट किया गया है ... मैन्युअल रूप से? इस ओपी ने
स्टैकओवरफ्लो

अच्छा उदाहरण! धन्यवाद!
विक्टर हाइन

ऐसे उदाहरण के लिए धन्यवाद! dereferencing pointer to incomplete typeवास्तव में मेरा मामला था!
तैमूर फैज़्रखमानोव

मैं केवल यह जोड़ना चाहूंगा कि सभी सार्वजनिक रूप से सुलभ संरचनाएं खराब नहीं हैं: आप उदाहरण के लिए अपने एपीआई के उपयोगकर्ता को डेटा में भरने और इसे भेजने के लिए सक्षम करना चाहते हैं।
अलेक्जेंडर टॉर्टलिंग

@ Mahesha999, वहाँ कोई जादू नहीं है। यू कोड कचरा डालते हैं तो भी एसओ हाइलाइट कोड। ध्यान दें कि यह कमांड लाइन आउटपुट को बाद में पोस्ट में हाइलाइट करने की कोशिश कर रहा है।
विंगर सेंडोन

8

यदि संरचना को अन्य संकलन इकाइयों (.c फ़ाइलों) द्वारा उपयोग किया जाना है, तो इसे हेडर फ़ाइल में रखें ताकि आप जहाँ भी ज़रूरत हो, उस हेडर फ़ाइल को शामिल कर सकें।

यदि संरचना केवल एक संकलन इकाई (.c फ़ाइल) में उपयोग की जाती है, तो आप इसे उस .c फ़ाइल में रखते हैं।


3

बिंदु यह है कि, इसे हेडर फ़ाइल में रखने से आप केवल हेडर फ़ाइल को शामिल करके कई स्रोत फ़ाइलों से संरचना (या किसी अन्य परिभाषा) का उपयोग कर सकते हैं।

लेकिन अगर आपको यकीन है कि इसका उपयोग केवल एक स्रोत फ़ाइल से किया जाएगा, तो यह वास्तव में कोई फर्क नहीं पड़ता है।



-4

आम तौर पर, मुझे नहीं लगता कि इससे कोई फर्क पड़ता है कि आप उन्हें हेडर या स्रोत फ़ाइलों में रखते हैं या नहीं। हालाँकि, यदि आपको कई स्रोत फ़ाइलों से संरचना के सदस्यों तक पहुँचने की आवश्यकता है, तो संरचना को हेडर फ़ाइल में रखना आसान है और इसे किसी अन्य फ़ाइल से सम्मिलित करना जहाँ संरचना की आवश्यकता है।


8
-1: यदि आप अच्छे सॉफ्टवेयर इंजीनियरिंग (एब्सट्रैक्शन, मॉड्युलैरिटी इत्यादि) की परवाह करते हैं, तो यह वास्तव में मायने रखता है जहां आप स्ट्रक्चर डेफिनिशन डालते हैं
पॉल आर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.