2010-07-06 9 views
13

मुझे उत्सुकता है कि यहां एक अंतर या संरचना टाइप करने पर क्या अंतर है। क्या इन दो ब्लॉकों के बीच अर्थात् कोई अंतर है?सी में इन दो टाइपिफ़ शैलियों के बीच अंतर क्या हैं?

यह:

typedef enum { first, second, third } SomeEnum; 

और इस:

enum SomeEnum { first, second, third }; 
typedef enum SomeEnum SomeEnum; 

structs के लिए एक ही सौदा। मैंने दोनों उपयोग में देखा है, और वे दोनों सी या उद्देश्य-सी में एक ही काम करते हैं। क्या कोई वास्तविक अंतर है या क्या यह सिर्फ एक प्राथमिकता है जिसके लिए आप उपयोग कर सकते हैं?

उत्तर

15

अंतर यह है कि दूसरा दृष्टिकोण enum SomeEnum नामक एक प्रकार की घोषणा करता है और उस प्रकार के लिए एक उपनाम टाइप किए गए नाम SomeEnum भी घोषित करता है। यह वास्तव में बराबर एक लाइनर

typedef enum SomeEnum { first, second, third } SomeEnum; 

जो कि दो दृष्टिकोणों के बीच फर्क सिर्फ इतना है enum कीवर्ड के बाद एक नाम लगा सकते हैं कि यह बजाय स्पष्ट करता है में जोड़ा जा सकता। दूसरे दृष्टिकोण के साथ, आप SomeEnum e या enum SomeEnum e का उपयोग करके उस एनम प्रकार के ऑब्जेक्ट को घोषित कर सकते हैं, जो भी आप चाहें।

पहला दृष्टिकोण केवल मूल रूप से अज्ञात enum प्रकार के लिए typedef-name SomeEnum घोषित करता है, जिसका अर्थ है कि आप SomeEnum e घोषणाओं तक सीमित हैं।

तो, जब तक आप केवल अपनी घोषणाओं में टाइप किए गए नाम SomeEnum का उपयोग करते हैं, तो दोनों के बीच कोई अंतर नहीं होगा। हालांकि, कुछ मामलों में आपको enum SomeEnum प्रकार के पूर्ण मूल नाम का उपयोग करना पड़ सकता है। पहले दृष्टिकोण में नाम उपलब्ध नहीं है, इसलिए आप भाग्य से बाहर होंगे।

उदाहरण के लिए, अगर इसके बाद के संस्करण घोषणा के बाद आप भी कुछ नेस्टेड गुंजाइश

int SomeEnum; 

वैरिएबल का नाम enum की typedef नाम छुपा देगा में SomeEnum नामक एक चर घोषित है, इस प्रकार इस घोषणा अवैध बनाने

SomeEnum e; /* ERROR: `SomeEnum` is not a type */ 

हालांकि, अगर आप दूसरा दृष्टिकोण जब अपने enum की घोषणा का इस्तेमाल किया है, तो आप इस समस्या को हल पूर्ण प्रकार का नाम

का उपयोग करके काम कर सकते हैं
enum SomeEnum e; /* OK */ 

यदि आप अपने एनम प्रकार की घोषणा करते समय पहले दृष्टिकोण का उपयोग करते हैं तो यह संभव नहीं होगा।

जब structs के साथ प्रयोग किया, struct के बाद नाम बहुत जरूरी है जब आप एक स्वत: संदर्भ प्रकार (एक प्रकार है कि एक ही प्रकार के लिए सूचक होता है) की जरूरत है,

typedef struct SomeStruct { 
    struct SomeStruct *next; 
} SomeStruct; 

की तरह अंत में, में दूसरा दृष्टिकोण टाइपपीफ नाम पूरी तरह से वैकल्पिक है। आप बस

enum SomeEnum { first, second, third }; 

घोषणा कर सकते हैं और सिर्फ हर बार जब आप इस प्रकार का उल्लेख करने की जरूरत है enum SomeEnum का उपयोग करें।

7

हां, एक अर्थपूर्ण अंतर है। दूसरा स्निपेट एक टैग पहचानकर्ता घोषित करता है, लेकिन पहला नहीं है। दोनों एक साधारण पहचानकर्ता घोषित करते हैं।

इसका मतलब है कि पहले के लिए, इस कोड को मान्य नहीं है, लेकिन दूसरे के लिए, यह है:

enum SomeEnum foo; 

जहाँ तक मुझे पता है, आपकी कोड में उन दोनों के बीच कोई अन्य अर्थ का अंतर है। structs और यूनियनों, दूसरा रूप है, शायद एक घोषणा में typedef के साथ संयुक्त के लिए, पुनरावर्ती प्रकार

typedef struct node { 
    struct node *parent; // refer to the tag identifier 
} node; 

साधारण पहचानकर्ता अभी तक struct के विनिर्देशक में दिखाई नहीं देता है, और इस तरह आप का उल्लेख करने की जरूरत के लिए आवश्यक है पहले से घोषित टैग पहचानकर्ता द्वारा संरचना। टैग पहचानकर्ताओं को उन्हें "संरचना", "संघ" या "enum" द्वारा प्रीपेड करके संदर्भित किया जाता है, जबकि सामान्य पहचानकर्ताओं को उपसर्ग के बिना संदर्भित किया जाता है (इस प्रकार नाम "सामान्य")।

/* forward declaration */ 
struct foo; 

/* for pointers, forward declarations are entirely sufficient */ 
struct foo *pfoo = ...; 

/* ... and then later define its contents */ 
struct foo { 
    /* ... */ 
}; 

नाम typedef पर बार-बार घोषित नहीं किया जा सकता है:

पहचानकर्ता है कि उन है कि मूल्यों को देखें से structs, यूनियनों और enumerations का उल्लेख अलग इसके अलावा, टैग पहचानने के लिए भी उपयोगी आगे घोषणाओं बनाने के लिए कर रहे हैं एक ही दायरा (सी ++ के विपरीत जहां वे कर सकते हैं), और उन्हें मौजूदा प्रकार का संदर्भ देने की आवश्यकता है, ताकि आगे की घोषणाओं के लिए उनका उपयोग नहीं किया जा सके।

enum SomeEnum x; 

जबकि पहले केवल का समर्थन करता है:

4

केवल वास्तविक अंतर यह है कि दूसरे मामले में, आप की तरह कुछ का उपयोग कर सकते है

SomeEnum x; 

लोगों के लिए किया है जो लिख रहा सी struct परिभाषित करने के लिए struct कीवर्ड को अक्सर "अजीब" लगता है ...

2

पहला फॉर्म अज्ञात enum प्रकार बनाता है और इसमें SomeEnum उपनाम बनाता है।

दूसरा फॉर्म enum SomeEnum प्रकार और SomeEnum उपनाम दोनों बनाता है।

(सी में, प्रकारों के लिए अलग-अलग नामस्थान हैं। यानी struct Fooenum Foo से अलग है जो Foo से अलग है।)

के लिए यह enum से अधिक महत्वपूर्ण है क्योंकि आपको struct स्वयं-रेफरेंसियल होने पर दूसरे फॉर्म का उपयोग करने की आवश्यकता होगी। उदाहरण के लिए:

struct LinkedListNode 
{ 
    void* item; 
    struct LinkedListNode* next; 
}; 

typedef struct LinkedListNode LinkedListNode; 

उपर्युक्त पहले फॉर्म के साथ संभव नहीं होगा।

0

struct के लिए एक वास्तविक अंतर है जो बस नामकरण के बारे में नहीं है।बिना

typedef struct { SomeEnum *first; } SomeEnum; 
0

user207442 की टिप्पणी को जोड़ना, यह संभव एक स्रोत कोड मॉड्यूल प्रकार के चर घोषित करने के लिए के लिए "struct foo *" है:

struct SomeEnum { struct SomeEnum *first; }; 

यह नहीं है:

यह मान्य सी है कभी भी संरचना के लिए एक परिभाषा है। ऐसा मॉड्यूल ऐसे पॉइंटर्स को कम करने में सक्षम नहीं होगा, लेकिन उन्हें अन्य मॉड्यूल से और पास कर सकता है।

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

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