2011-02-23 21 views
6

में typedef का उपयोग कर एक नया डेटाप्रकार सी में उदाहरण के लिए लिंक्ड सूची
एक के लिए एक प्रकार को परिभाषित करने निम्नलिखित परिभाषाउपयोग सूचक struct या जब सी

struct list_node { 
    int x; 
    struct list_node * next; 
}; 

//1 
typedef struct list_node list1; 
//2 
typedef struct list_node *list2; 

में से एक का उपयोग कर सकते कि मैं क्या है से में नहीं करने के लिए सामान्य अभ्यास पहली परिभाषा है देखा।

सवाल यह है कि यदि दूसरी परिभाषा भी एक स्वीकार्य अभ्यास है। किस मामले में किसी को पहले दूसरे को पसंद करना चाहिए? बशर्ते कि हमारे द्वारा उपयोग किए जाने वाले वेरिएबल स्ट्रक्चर सूची_नोड पर पॉइंटर्स हैं, क्या दोनों प्रकार के साथ समान ऑपरेशन करना संभव है? पहले के फायदे क्या हैं?

+0

इसी प्रकार का प्रश्न: http://stackoverflow.com/questions/3781932/is-typedefing-a-pointer-type-cononsidered-bad-practice –

+0

या न तो ... :) – alternative

उत्तर

5

मुझे एपीआई उपयोगकर्ताओं को "*" टाइप करने की आवश्यकता होगी, यानी स्ट्रिप टाइप करें, संरचना के लिए सूचक नहीं। यह जीएलआईबी में व्यापक रूप से उपयोग की जाने वाली शैली है, जो कि अधिक लोकप्रिय सी स्टैक में से एक है।

यह अच्छी तरह से काम करता है क्योंकि यह यह जानना महत्वपूर्ण है कि आपके पास संरचना या संरचना के लिए सूचक है या नहीं। उदाहरण के लिए, क्या आप प्रकार के चर में न्यूल स्टोर कर सकते हैं? यदि आप छुपाते हैं कि ऑब्जेक्ट एक पॉइंटर है, तो आपको NULL को प्रतिस्थापित करने के लिए एक विशेष NIL_NODE या अन्य मान बनाना होगा। यदि आप इसे एक सूचक बनाते हैं, तो लोग इसे एक जैसा व्यवहार कर सकते हैं।

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

फिर भी इस पथ को लेने का एक अन्य कारण यह है कि कभी-कभी आप एक ऐसी संरचना चाहते हैं जिसे कॉपी किया जा सके, और आप अभी भी इसे टाइप करना चाहते हैं। GdkPoint की तरह एक बात लें:

typedef struct { 
    int x, y; 
    } GdkPoint; 

यहाँ यह प्रत्यक्ष struct उपयोग की अनुमति के लिए उपयोगी है, जैसे:,

GdkPoint point = { 10, 10 }; 
GdkPoint copy = point; 
do_stuff_with_point(&copy); 

लेकिन अगर आपके सम्मेलन है कि "GdkPoint" typedef एक सूचक हो सकता है, आप ' असंगत होना होगा।

कोड केवल स्पष्ट है अगर आप यह बता सकते हैं कि कोई सूचक क्या है और क्या नहीं है, और यदि आप हेडर में स्ट्रक्चर परिभाषाएं नहीं डालते हैं तो कोड बेहतर होता है (ऐसे structs के लिए जो अमूर्त, अपारदर्शी डेटा प्रकारों का प्रतिनिधित्व करते हैं, जो कि है शायद सबसे आम तरह)।

एक सी डेटा प्रकार के लिए मेरे डिफ़ॉल्ट टेम्पलेट शीर्षक में कुछ इस तरह है:

typedef struct MyType MyType; 
MyType* my_type_new(void); 
void my_type_unref(MyType *t); 
void my_type_ref(MyType *t); 

वास्तविक "struct MyType" ग फ़ाइल में फिर, नए, unref के साथ-साथ, और किसी भी प्रकार पर संचालन।

अपवाद पॉइंट, आयत, रंग जैसे प्रकारों के लिए होगा जहां यह "सादा पुराना डेटा" है और प्रत्यक्ष क्षेत्र का उपयोग वांछित है; अगर आपको refcounting की आवश्यकता नहीं है तो _unref() के बजाय my_type_free() एक और भिन्नता है।

किसी भी तरह, यह एक शैली है, मूल रूप से जीएलआईबी शैली, जिसका व्यापक रूप से उपयोग किया जाता है और अच्छी तरह से काम करने के लिए जाना जाता है।

+2

मैं पूरी तरह से सहमत हूं। यह टाइप करने के लिए आमतौर पर 'टाइपपीफ' का उपयोग करने का अच्छा विचार नहीं है कि कोई प्रकार एक सूचक या संरचना है (जब तक कि आप लाइब्रेरी इंटरफ़ेस के लिए अपारदर्शी पॉइंटर्स का उपयोग नहीं कर रहे हों)। ईमानदार होने के लिए मैं आम तौर पर 'स्ट्रक्चर' को 'स्ट्रक्चर' कॉल करना पसंद करता हूं और 'टाइपेडफ' से पूरी तरह से बचता हूं लेकिन यदि आप 'टाइपपीफ' पर जा रहे हैं, तो इसे संरचना बनाएं, न कि पॉइंटर। – bta

+0

ग्लिब स्टाइल कैमलकेस का उपयोग स्ट्रिप टाइपिफ़ और वर्चुअल टाइप टाइपपीफ के लिए लोअरकेस के लिए करेगा, इसलिए चीजों को स्पष्ट करते समय "स्ट्रक्चर" टाइप करने की आवश्यकता को हटा दिया जाता है। हेडर में अपारदर्शी structs नहीं होने की क्षमता को भी संरक्षित करता है –

0

इन दोनों का उपयोग कर पर विचार करें:

typedef struct list_node Node; 
typedef Node* ListHead; 
1

मैं पहली बार शैली पसंद करते हैं, तो यह स्पष्ट है जो प्रकार वस्तुओं रहे हैं, और जो प्रकार संकेत दिए गए हैं। लेकिन मुझे सी पॉइंटर्स को समझने/समझने में आसान लगता है, जो (स्पष्ट रूप से) बहुत से लोग नहीं करते हैं। इसलिए यदि आपको लगता है कि आपके कोड बेस को पढ़ने वाले अधिकांश लोग पॉइंटर्स को समझ नहीं पाएंगे, तो Win32 API की तरह हर जगह typedef STRUCT_FOO *PSTRUCT_FOO का उपयोग करें।

0

जब तक पहचानकर्ता यह स्पष्ट करता है कि यह एक सूचक है तो कोई नुकसान नहीं होता है (मैं व्यक्तिगत रूप से एक प्रत्यय अला _Pointer या _Ptr पसंद करता हूं, लेकिन जो भी परियोजना के अनुरूप है)। उस ने कहा, सी-केवल कोड के लिए स्पष्ट * से बचने में कोई वास्तविक लाभ नहीं है। मिश्रित सी/सी ++ वातावरण या शुद्ध सी ++ के लिए, मैंने अक्सर typedef एस के पॉइंटर्स को तर्कसंगत/उचित पुन: उपयोग करने के लिए स्मार्ट पॉइंटर प्रकारों के बीच संक्रमण, उपयोग और स्विचिंग की सुविधा प्रदान की है। शायद इसके लिए कुछ सच्चाई है, हालांकि मैंने खुद को अभ्यास को अपनाने के लिए कभी नहीं पाया है।

0

टाइपपीफ int * ptr_int; ptr_int x, y, z;

प्रोग्रामर भ्रमित हो सकता है कि सभी तीन एक्स, वाई, जेड int * प्रकार i.e. int के लिए पॉइंटर्स हैं। लेकिन वास्तविकता में केवल x int * टाइप y और z सरल int है।

क्योंकि ptr_int x, y, z; int * x, y, z के बराबर है; int * x, * y, * z नहीं;

तो, टाइपपीफ प्रोग्रामर दिमाग में भी भ्रम पैदा करता है और इससे बग और त्रुटियां हो सकती हैं।

संबंधित मुद्दे