2015-09-04 2 views
10

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

typedef void* vpoint_t; 

typedef struct queue_item_t{ 
    vpoint_t void_item; 
    struct queue_item_t* next; 
} queue_item_t; 
+2

संभावित उत्तर: http://stackoverflow.com/questions/252780/why-should-we-typedef-a-struct-so-often-in-c – Paulo

+1

कभी भी संरचना नाम और समान प्रकार के नाम का उपयोग करने का सुझाव न दें। 'Typedef struct QUEUE_ITEM {...} queue_item_t;' –

+4

दोबारा खोलने के लिए वोट दिया गया है, क्योंकि डुप्लिकेट सवाल एक ही सटीक चीज़ नहीं पूछ रहा था। –

उत्तर

13
typedef struct queue_item_t {  // 1 
    vpoint_t void_item; 
    struct queue_item_t* next;  // 2 
} queue_item_t;     // 3 

सबसे पहले, ध्यान दें कि इस पूरे बयान एक typedef को परिभाषित किया गया है।

3) कह रहा है कि नए प्रकार हम (typedef के माध्यम से) को परिभाषित करने की प्रक्रिया में हैं के लिए जा रहा queue_item_t नाम दिया है।

1) संरचना का नाम (जिसे एक नया नाम दिया जा रहा है, जैसा कि हम जाते हैं) का नाम struct queue_item_t रखा गया है। यह पूरा नाम है, जिसमें सामने struct शामिल है।

2) क्योंकि नए प्रकार अभी तक (याद रखें, हम अभी भी यह परिभाषित करने की प्रक्रिया में हैं) मौजूद नहीं है, हम से, केवल नाम यह अब तक है, जो struct queue_item_t है उपयोग करने के लिए 1)


नोट आप गुमनाम struct परिभाषाओं, जो आप से 1) नाम हटा दें करने की अनुमति हो सकता है। एक साधारण उदाहरण:

typedef struct { 
    int x, y, z; 
} vector3; 

अपने उदाहरण में हालांकि, के बाद से हम संरचना की जरूरत है खुद को संदर्भित करने में सक्षम हो, next सूचक एक प्रकार है कि पहले से ही परिभाषित किया है होना आवश्यक है।

struct _queue_item;       // 4 

typedef struct _queue_item queue_item_t;  // 5 

struct _queue_item {       // 6 
    vpoint_t void_item; 
    queue_item_t* next;       // 7 
} 

4) घोषित कि struct _queue_item मौजूद है, लेकिन अभी तक एक प्रदान नहीं करते हैं: हम कि से आगे struct की घोषणा, यह typedefing, तो next के लिए struct typedef घ प्रकार का उपयोग को परिभाषित कर सकते हैं इसके लिए परिभाषा।

5) टाइपपीफ queue_item_tstruct _queue_item जैसा ही होना चाहिए।

6) संरचना अब की परिभाषा दें ...

7) ... का उपयोग कर हमारे typedef 'queue_item_t d।


यह सब कहा जा रहा है ... मेरी राय में, please don't use typedefs for structs

struct queue_item { 
    void *data; 
    struct queue_item *next; 
} 

सरल और पूर्ण है। आप उन छह अतिरिक्त पात्रों को टाइप करने के लिए प्रबंधित कर सकते हैं।

Linux Kernel coding style से

:

अध्याय 5: typedefs

कृपया की तरह "vps_t" चीजों का उपयोग नहीं करते। संरचनाओं और पॉइंटर्स के लिए टाइपपीफ का उपयोग करने के लिए यह गलती है। जब आप

vps_t a; 

स्रोत में, इसका क्या अर्थ है? इसके विपरीत, यदि यह कहते हैं

struct virtual_container *a; 

आप वास्तव में बता सकते हैं क्या "एक" है।

अपवाद हैं, जिन्हें आप पढ़ सकते हैं।


कुछ हाल ही में संबंधित प्रश्नों:

+0

नोट: मुझे लगता है कि यहां 'स्ट्रक्चर' के बारे में सबकुछ 'संघ' पर लागू होता है। – chux

+0

टाइपपीफ का अनुशासित उपयोग ठीक है। लिनस इसे पसंद नहीं करता है; यह केवल तभी मायने रखता है जब लिनक्स कर्नेल कोड लिखना। पागल क्या है "typedef struct foo {..} foo_t" के साथ "टाइपपीफ स्ट्रक्चर बार {...} * bar_t" और इसी तरह के कोड obfuscation मिश्रण। या बकवास "#define foo_t struct foo" जैसे बकवास। –

0

पहले, मैं कभी नहीं एक struct नाम और समान प्रकार नाम का उपयोग करने का सुझाव देते हैं। typedef struct QUEUE_ITEM {...} queue_item_t;

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

struct T { 
    ... 
    struct T *ptr; 
    .... 
}; 

अंतिम } queue_item_t; आप संरचना के लिए एक नया नाम बनाने के साथ ऐसा करने के लिए।

+2

आप सुझाव देते हैं कि कभी भी संरचना नाम और समान प्रकार का नाम क्यों न दें? –

+0

क्योंकि यह भ्रमित है और थोड़ा जानता है कि थाई दो अलग-अलग नाम रिक्त स्थान (टैग और टाइपपीफ) में हैं। –

0

"स्ट्रक्चर फू {...}" एक बात है। यह एक संरचना को परिभाषित करता है, आपको हर जगह उस स्थान पर "स्ट्रक्चर फू" टाइप करने की आवश्यकता होती है।

"typedef ... foo" एक नए प्रकार को परिभाषित करता है, इसलिए आप इसे "foo" टाइप करते हैं जहां आप इसका उपयोग करते हैं।

"टाइपपीफ स्ट्रक्चर फू {...} foo" एक मुहावरे है ताकि आप दोनों का उपयोग कर सकें, संभवतः केवल "foo" कीस्ट्रोक और दृश्य प्रदूषण को बचाने के लिए।

+1

'typedef struct foo {struct foo * next} foo;' compiles, 'typedef struct {foo * next} foo; 'संकलित नहीं होता है, इसलिए मुहावरे का उद्देश्य एक पॉइंटर-टू-द-स्ट्रक्चर होने की अनुमति देना है संरचना में ही शामिल है। – user3386109

4

की घोषणा एक छोटा सा बदल चर्चा आसान बनाने के लिए पालन करने के लिए करते हैं:

typedef struct queue_item { 
    vpoint_t void_item; 
    struct queue_item* next; 
} QueueItemType; 

सी कई अलग अलग नाम रिक्त स्थान समर्थन करता है; यूनियन, संरचनाओं और गणना प्रकारों पर टैग नाम के लिए एक नाम स्थान आरक्षित है। इस मामले में, टैग का नाम queue_item है। टाइपपीफ नाम जैसे QueueItemType सहित नियमित पहचानकर्ताओं के लिए एक अन्य नाम स्थान आरक्षित है।

next सदस्य struct queue_item (यानी, कतार में अगला आइटम) के दूसरे उदाहरण को इंगित करने के लिए उपयोग किया जा रहा है। यह दो कारणों के लिए struct queue_item के सूचक के रूप में घोषित किया है:

  • एक struct प्रकार में ही की एक उदाहरण नहीं हो सकता; एक बात के लिए, प्रकार असीम बड़े (struct queue_item एक सदस्य next है, जो एक struct queue_item कि एक सदस्य next है, जो एक struct queue_item कि एक सदस्य next, अनंत तक शामिल होता है शामिल हैं) होना चाहिए था;

  • struct प्रकार परिभाषा नहीं पूरा है समापन } जब तक है, और आप एक अधूरी प्रकार का एक उदाहरण की घोषणा नहीं कर सकते हैं। हालांकि, आप एक अपूर्ण प्रकार के लिए पॉइंटर घोषित कर सकते हैं, जो हम नीचे करते हैं:

    संरचना queue_item * अगला;

क्यों नहीं QueueItemType *next; बजाय struct queue_item *next का उपयोग करें? फिर, next बिंदु पर संरचना प्रकार परिभाषा पूर्ण नहीं है; टाइपपीफ नाम QueueItemType अभी तक मौजूद नहीं है। हालांकि, टैग नाम queue_item पहले से ही संकलक के लिए दृश्यमान है, इसलिए हम struct queue_item प्रकार का उपयोग कर पॉइंटर्स घोषित कर सकते हैं।

चूंकि टैग नाम और टाइपपीफ नाम अलग-अलग नाम रिक्त स्थान पर हैं, इसलिए टकराव के बिना टैग नाम और टाइपपीफ नाम दोनों के लिए समान नाम का उपयोग करना संभव है। संकलक struct कीवर्ड की उपस्थिति से दोनों के बीच असंबद्ध हो जाता है।

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