2008-10-31 14 views

उत्तर

26

यूनियन डेटा सदस्यों जो परस्पर अनन्य हैं उसी स्मृति साझा करने के लिए अनुमति देते हैं। यह काफी महत्वपूर्ण है जब स्मृति अधिक दुर्लभ है, जैसे एम्बेडेड सिस्टम में।

निम्न उदाहरण में:

union { 
    int a; 
    int b; 
    int c; 
} myUnion; 

यह संघ एक भी int की जगह के बजाय 3 अलग पूर्णांक मान ले जाएगा। यदि उपयोगकर्ता का मान सेट करता है, और उसके बाद b का मान सेट करता है, तो यह के मान को ओवरराइट करेगा क्योंकि वे दोनों एक ही स्मृति स्थान साझा कर रहे हैं।

4

यूनियन इस्तेमाल किया जब तुम हार्डवेयर, उपकरणों या नेटवर्क प्रोटोकॉल, या जब आप वस्तुओं की एक बड़ी संख्या बना रहे हैं और स्थान बचाना चाहते हैं द्वारा परिभाषित structs मॉडल बनाना चाहते हैं कर रहे हैं। हालांकि, आपको वास्तव में 9 5% समय की आवश्यकता नहीं है, हालांकि आसान-से-डीबग कोड के साथ चिपके रहें।

216

यूनियन अक्सर पूर्णांकों का बाइनरी अभ्यावेदन के बीच परिवर्तित करने के लिए इस्तेमाल किया और तैरता रहे हैं:

union 
{ 
    int i; 
    float f; 
} u; 

// Convert floating-point bits to integer: 
u.f = 3.14159f; 
printf("As integer: %08x\n", u.i); 

हालांकि यह तकनीकी रूप से अपरिभाषित व्यवहार सी मानक के अनुसार (यदि आप मात्र क्षेत्र है जिसमें सबसे अधिक था पढ़ने के लिए चाहिए रहे हैं हाल ही में लिखा गया है), यह लगभग किसी भी कंपाइलर में एक अच्छी तरह परिभाषित तरीके से कार्य करेगा।

यूनियन भी कभी कभी, सी में छद्म बहुरूपता लागू करने के लिए उपयोग किया जाता है एक संरचना कुछ टैग का संकेत इसमें वस्तु की किस प्रकार दे रही है, और फिर संभव प्रकार एक साथ unioning द्वारा:

enum Type { INTS, FLOATS, DOUBLE }; 
struct S 
{ 
    Type s_type; 
    union 
    { 
    int s_ints[2]; 
    float s_floats[2]; 
    double s_double; 
    }; 
}; 

void do_something(struct S *s) 
{ 
    switch(s->s_type) 
    { 
    case INTS: // do something with s->s_ints 
     break; 

    case FLOATS: // do something with s->s_floats 
     break; 

    case DOUBLE: // do something with s->s_double 
     break; 
    } 
} 

इस आकार की अनुमति देता है struct S के बजाय 28.

+0

u.f –

+0

के बजाय u.y होना चाहिए उदाहरण क्या फ्लोट को पूर्णांक में परिवर्तित करने का अनुमान है? मुझे ऐसा नहीं लगता है, क्योंकि int और float स्मृति में विभिन्न प्रारूपों में संग्रहीत हैं। क्या आप अपना उदाहरण समझा सकते हैं? –

+3

@spin_eight: यह फ्लोट से int तक "रूपांतरित नहीं" है। जैसे "एक फ्लोट के द्विआधारी प्रतिनिधित्व को दोबारा परिभाषित करना जैसे कि यह एक int था"। आउटपुट 3 नहीं है: http://ideone.com/MKjwon मुझे यकीन नहीं है कि क्यों एडम हेक्स के रूप में प्रिंट कर रहा है। – endolith

5

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

यूनियन अन्य भाषाओं में भिन्न प्रकारों की तरह हैं - वे एक समय में केवल एक ही चीज़ धारण कर सकते हैं, लेकिन यह बात यह है कि आप इसे कैसे घोषित करते हैं इसके आधार पर यह चीज एक इंट, फ्लोट इत्यादि हो सकती है।

उदाहरण के लिए:

typedef union MyUnion MYUNION; 
union MyUnion 
{ 
    int MyInt; 
    float MyFloat; 
}; 

MyUnion केवल एक पूर्णांक या एक नाव में शामिल होंगे, जो के आधार पर आप सबसे हाल ही में निर्धारित किया है। तो यह कर:

MYUNION u; 
u.MyInt = 10; 

अब यू को पूर्णांक में 10 के बराबर रखती है;

u.MyFloat = 1.0; 

यू अब एक नाव 1.0 के बराबर है। यह अब एक int रखता है। जाहिर है अब अगर आप कोशिश करते हैं और printf कर ("मींट =% d", u.MyInt); तो आपको शायद एक त्रुटि मिल जाएगी, हालांकि मैं विशिष्ट व्यवहार से अनिश्चित हूं।

संघ का आकार इस मामले नाव में, अपने सबसे बड़े मैदान के आकार से निर्धारित होता।

+1

'आकार (int) == आकार (फ्लोट) '(' == 32') आमतौर पर। –

+1

रिकॉर्ड के लिए, फ्लोट को असाइन करने के बाद int को प्रिंट नहीं किया जाएगा * नहीं * त्रुटि का कारण होगा, न कि संकलक और न ही रन-टाइम पर्यावरण * पता * कौन सा मान मान्य है। मुद्रित होने वाला int, निश्चित रूप से, अधिकांश उद्देश्यों के लिए व्यर्थ होगा। यह केवल एक इंट के रूप में व्याख्या की गई फ्लोट का स्मृति प्रतिनिधित्व होगा। –

1

यूनियन महान हैं। मैंने देखा है कि यूनियनों का एक चालाक उपयोग किसी घटना को परिभाषित करते समय उनका उपयोग करना है। उदाहरण के लिए, आप तय कर सकते हैं कि एक घटना 32 बिट्स है।

अब, 32 बिट्स के भीतर, आप घटना के प्रेषक के पहचानकर्ता के लिए पहली 8 बिट्स को नामित करना चाहेंगे ... कभी-कभी आप पूरी तरह से घटना से निपटते हैं, कभी-कभी आप इसे विच्छेदन करते हैं और इसकी तुलना करते हैं अवयव। संघ आपको दोनों को करने के लिए लचीलापन देते हैं।

 
union Event 
{ 
    unsigned long eventCode; 
    unsigned char eventParts[4]; 
}; 
16

यहाँ मेरे अपने codebase से एक संघ का एक उदाहरण (स्मृति से और दूसरे शब्दों में बयान तो यह सही नहीं हो सकता है) है। इसका इस्तेमाल मेरे द्वारा बनाए गए दुभाषिया में भाषा तत्वों को संग्रहीत करने के लिए किया गया था। उदाहरण के लिए, निम्न कोड:

set a to b times 7. 

निम्न भाषा तत्वों के होते हैं:

  • प्रतीक [सेट]
  • चर [एक]
  • [के लिए] प्रतीक
  • चर [ बी]
  • प्रतीक [समय]
  • स्थिर [7]
  • [।] तो

    typedef struct { 
        int typ; 
        union { 
         char *str; 
         int val; 
        } 
    } tElem; 
    

    :

    #define ELEM_SYM_SET  0 
    #define ELEM_SYM_TO   1 
    #define ELEM_SYM_TIMES  2 
    #define ELEM_SYM_FULLSTOP 3 
    #define ELEM_VARIABLE  100 
    #define ELEM_CONSTANT  101 
    

    और निम्नलिखित संरचना प्रत्येक तत्व स्टोर करने के लिए इस्तेमाल किया गया था

  • प्रतीक

भाषा तत्वों '#define' इस प्रकार मूल्यों के रूप में परिभाषित करता है थे प्रत्येक तत्व का आकार अधिकतम संघ का आकार था (प्रकार के लिए 4 बाइट्स और संघ के लिए 4 बाइट्स, हालांकि वे सामान्य मान हैं, वास्तविक आकार कार्यान्वयन पर निर्भर करते हैं)।

आदेश में एक तत्व "सेट" बनाने के लिए, आप का प्रयोग करेंगे:

tElem e; 
e.typ = ELEM_SYM_SET; 

आदेश में एक "चर [ख]" तत्व बनाने के लिए, आप का प्रयोग करेंगे:

tElem e; 
e.typ = ELEM_VARIABLE; 
e.str = strdup ("b"); // make sure you free this later 

में आदेश में एक "निरंतर [7]" तत्व बनाने के लिए, आप का प्रयोग करेंगे:

tElem e; 
e.typ = ELEM_CONSTANT; 
e.val = 7; 

और आप आसानी से तैरता शामिल करने के लिए यह विस्तार कर सकता है (float flt) या राशन (struct ratnl {int num; int denom;}) और अन्य प्रकार।

मूल आधार है कि str और val स्मृति में सन्निहित नहीं हैं, वे वास्तव में ओवरलैप, तो यह जहां संरचना स्मृति स्थान पर आधारित है स्मृति का एक ही खंड पर एक अलग दृष्टिकोण हो रही है, यहाँ दिखाया गया है, का एक तरीका है

 +-----------+ 
0x1010 |   | 
0x1011 | typ | 
0x1012 |   | 
0x1013 |   | 
     +-----+-----+ 
0x1014 |  |  | 
0x1015 | str | val | 
0x1016 |  |  | 
0x1017 |  |  | 
     +-----+-----+ 

यदि यह महज एक संरचना में थे, यह इस प्रकार दिखाई देगा:

 +-------+ 
0x1010 |  | 
0x1011 | typ | 
0x1012 |  | 
0x1013 |  | 
     +-------+ 
0x1014 |  | 
0x1015 | str | 
0x1016 |  | 
0x1017 |  | 
     +-------+ 
0x1018 |  | 
0x1019 | val | 
0x101A |  | 
0x101B |  | 
     +-------+ 
+0

क्या यह सुनिश्चित करना चाहिए कि आप इस बाद की टिप्पणी को मुक्त तत्व से हटा दें? – Trevor

+0

हां, @ ट्रेवर, हालांकि मुझे विश्वास नहीं है कि आप पहले व्यक्ति हैं जिन्होंने इसे पिछले 4+ सालों में देखा :-) फिक्स्ड, और इसके लिए धन्यवाद। – paxdiablo

105

यूनियन एंबेडेड programm में विशेष रूप से उपयोगी हैं 0x1010 और पूर्णांकों और संकेत दिए गए दोनों 4 बाइट हैं आईएनजी या परिस्थितियों में जहां हार्डवेयर/मेमोरी की सीधी पहुंच की आवश्यकता होती है। इस प्रकार

typedef union 
{ 
    struct { 
     unsigned char byte1; 
     unsigned char byte2; 
     unsigned char byte3; 
     unsigned char byte4; 
    } bytes; 
    unsigned int dword; 
} HW_Register; 
HW_Register reg; 

तो फिर तुम reg उपयोग कर सकते हैं:

reg.dword = 0x12345678; 
reg.bytes.byte3 = 4; 

endianness (बाइट क्रम) और प्रोसेसर आर्किटेक्चर निश्चित रूप से कर रहे हैं महत्वपूर्ण यहाँ एक तुच्छ उदाहरण है।

एक और उपयोगी सुविधा बिट संशोधक है:

typedef union 
{ 
    struct { 
     unsigned char b1:1; 
     unsigned char b2:1; 
     unsigned char b3:1; 
     unsigned char b4:1; 
     unsigned char reserved:4; 
    } bits; 
    unsigned char byte; 
} HW_RegisterB; 
HW_RegisterB reg; 

इस कोड को आप सीधे उपयोग कर सकते हैं के साथ रजिस्टर/स्मृति पते में एक भी बिट:

x = reg.bits.b2; 
1

क्या VARIANT के बारे में है कि प्रयोग किया जाता है COM इंटरफेस? इसमें दो फ़ील्ड हैं - "टाइप" और एक यूनियन जो वास्तविक मूल्य धारण करता है जिसे "टाइप" फ़ील्ड के आधार पर माना जाता है।

1

जब मैं एम्बेडेड डिवाइसों के लिए कोडिंग कर रहा था तो मैंने संघ का उपयोग किया। मेरे पास सी int है जो 16 बिट लंबा है। और जब मुझे ईईपीरोम से स्टोर/स्टोर करने की आवश्यकता होती है तो मुझे उच्च 8 बिट्स और निचले 8 बिट्स को पुनर्प्राप्त करने की आवश्यकता होती है। तो मैंने इस तरह से उपयोग किया:

union data { 
    int data; 
    struct { 
     unsigned char higher; 
     unsigned char lower; 
    } parts; 
}; 

इसे स्थानांतरित करने की आवश्यकता नहीं है ताकि कोड पढ़ने में आसान हो।

दूसरी ओर, मैंने कुछ पुराने सी ++ एसएलएल कोड देखा जो एसएलएल आवंटक के लिए संघ का उपयोग करता था। यदि आप रुचि रखते हैं, तो आप sgi stl स्रोत कोड पढ़ सकते हैं।

union _Obj { 
    union _Obj* _M_free_list_link; 
    char _M_client_data[1]; /* The client sees this.  */ 
}; 
+1

क्या आपको अपने 'उच्च'/'निचले' के आस-पास समूह 'संरचना' की आवश्यकता नहीं होगी? अभी दोनों को केवल पहले बाइट को इंगित करना चाहिए। – Mario

+0

@ मारियो आह सही, मैं इसे हाथ से लिखता हूं और इसके बारे में भूल जाता हूं, धन्यवाद –

1
  • एक विभिन्न प्रकार के रिकॉर्ड युक्त फ़ाइल: यहाँ यह का एक टुकड़ा है।
  • एक नेटवर्क इंटरफ़ेस जिसमें विभिन्न अनुरोध प्रकार होते हैं।

इस पर एक नज़र डालें: X.25 buffer command handling

कई संभावित X.25 आदेशों से एक एक बफर में प्राप्त हुआ है और सभी संभव संरचनाओं के एक संघ का उपयोग करके जगह में नियंत्रित किया जाता है।

+0

क्या आप इन दोनों उदाहरणों को समझा सकते हैं। मेरा मतलब है कि ये संघ –

6

मैं कहूंगा कि यह स्मृति का पुन: उपयोग करना आसान बनाता है जिसका उपयोग विभिन्न तरीकों से किया जा सकता है, यानी स्मृति को सहेजना। जैसे

struct variant { 
    int type; 
    double number; 
    char *string; 
}; 

एक 32 बिट प्रणाली इस कम से कम 96 बिट या 12 बाइट्स में परिणाम होगा में के लिए इस्तेमाल किया जा रहा: क्या आप कुछ "संस्करण" struct एक नंबर के साथ ही एक छोटी स्ट्रिंग बचाने में सक्षम है कि क्या करना चाहते हैं variant का प्रत्येक उदाहरण।

एक संघ का उपयोग करके आप 64 बिट्स या 8 बाइट्स के लिए नीचे आकार को कम कर सकते हैं:

struct variant { 
    int type; 
    union { 
     double number; 
     char *string; 
    } value; 
}; 

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

20

बहुत सारे उपयोग। बस grep union /usr/include/* या इसी निर्देशिका में करें। अधिकांश मामलों में unionstruct में लपेटा गया है और संरचना का एक सदस्य बताता है कि संघ में किस तत्व का उपयोग करना है। उदाहरण के लिए वास्तविक जीवन कार्यान्वयन के लिए चेकआउट man elf

यह बुनियादी सिद्धांत है:

typedef union 
{ 
    unsigned char color[4]; 
    int  new_color; 
}  u_color; 

मैं, यह प्रयोग किया जाता उपयोग करने के बजाय और अधिक आसानी से रंग को संभालने के लिए >> और < <:

struct _mydata { 
    int which_one; 
    union _data { 
      int a; 
      float b; 
      char c; 
    } foo; 
} bar; 

switch (bar.which_one) 
{ 
    case INTEGER : /* access bar.foo.a;*/ break; 
    case FLOATING : /* access bar.foo.b;*/ break; 
    case CHARACTER: /* access bar.foo.c;*/ break; 
} 
+0

से संबंधित हैं जो वास्तव में मैं देख रहा था! कुछ इलिप्सिस पैरामीटर को प्रतिस्थापित करने के लिए बहुत उपयोगी :) :) –

1

विद्यालय में, मैं इस तरह यूनियनों का इस्तेमाल किया ऑपरेटर, मुझे बस अपने चार सरणी के विभिन्न इंडेक्स से गुजरना पड़ा।

28

मैंने इसे ऑब्जेक्ट उन्मुख विरासत के प्रतिस्थापन के रूप में कुछ पुस्तकालयों में देखा है।

उदा।

 Connection 
    /  |  \ 
    Network USB  VirtualConnection 

आप कनेक्शन "वर्ग" ऊपर की या तो एक होने के लिए आपको कुछ ऐसा लिख ​​सकता है चाहते हैं: http://git.0x539.de/?p=infinote.git;a=blob;f=libinfinity/common/inf-session.c;h=3e887f0d63bd754c6b5ec232948027cbbf4d61fc;hb=HEAD#l74

48

कम स्तर प्रणाली प्रोग्रामिंग: libinfinity में उपयोग

struct Connection 
{ 
    int type; 
    union 
    { 
     struct Network network; 
     struct USB usb; 
     struct Virtual virtual; 
    } 
}; 

उदाहरण एक उचित उदाहरण है।

आईआईआरसी, मैंने घटक बिट्स में हार्डवेयर रजिस्टरों को तोड़ने के लिए यूनियनों का उपयोग किया है। तो, आप एक 8-बिट रजिस्टर तक पहुंच सकते हैं (जैसा कि मैंने किया था, जिस दिन मैंने यह किया था ;-) घटक बिट्स में।

(मैं सटीक वाक्यविन्यास भूल जाता हूं लेकिन ...) यह संरचना नियंत्रण नियंत्रक को नियंत्रण_बाइट या व्यक्तिगत बिट्स के माध्यम से एक्सेस करने की अनुमति देगी। किसी दिए गए अंतराल के लिए सही रजिस्टर बिट्स पर बिट्स मानचित्र को सुनिश्चित करना महत्वपूर्ण होगा।

typedef union { 
    unsigned char control_byte; 
    struct { 
     unsigned int nibble : 4; 
     unsigned int nmi  : 1; 
     unsigned int enabled : 1; 
     unsigned int fired : 1; 
     unsigned int control : 1; 
    }; 
} ControlRegister; 
+2

यह एक उत्कृष्ट उदाहरण है! यहां एक उदाहरण दिया गया है कि आप एम्बेडेड सॉफ़्टवेयर में इस तकनीक का उपयोग कैसे कर सकते हैं: http://www.edn.com/design/integrated-circuit-design/4394915/Managing-the-8--to-32-bit-processor- माइग्रेशन – rzetterberg

0

एक सरल और बहुत उपयोगी उदाहरण के लिए, है ....

कल्पना कीजिए:

आप एक uint32_t array[2] है और 3 और बाइट श्रृंखला के 4 बाइट का उपयोग करना चाहते हैं। आप *((uint16_t*) &array[1]) कर सकते हैं। लेकिन यह दुखद अलौकिक नियमों को दुखी करता है!

लेकिन जाना जाता compilers आप निम्नलिखित करने की अनुमति:

union un 
{ 
    uint16_t array16[4]; 
    uint32_t array32[2]; 
} 

तकनीकी रूप से यह अभी भी नियमों का उल्लंघन है। लेकिन सभी ज्ञात मानक इस उपयोग का समर्थन करते हैं।

3

इनमें से कई उत्तर एक प्रकार से दूसरे में कास्टिंग के साथ सौदा करते हैं। मुझे यूनियनों से उसी प्रकार के अधिक से अधिक उपयोग मिलते हैं (यानी जब एक सीरियल डेटा स्ट्रीम पार्स करते हैं)। वे के पार्सिंग/निर्माण को पैकेट को छोटे से बनने की अनुमति देते हैं।

typedef union 
{ 
    UINT8 buffer[PACKET_SIZE]; // Where the packet size is large enough for 
           // the entire set of fields (including the payload) 

    struct 
    { 
     UINT8 size; 
     UINT8 cmd; 
     UINT8 payload[PAYLOAD_SIZE]; 
     UINT8 crc; 
    } fields; 

}PACKET_T; 

// This should be called every time a new byte of data is ready 
// and point to the packet's buffer: 
// packet_builder(packet.buffer, new_data); 

void packet_builder(UINT8* buffer, UINT8 data) 
{ 
    static UINT8 received_bytes = 0; 

    // All range checking etc removed for brevity 

    buffer[received_bytes] = data; 
    received_bytes++; 

    // Using the struc only way adds lots of logic that relates "byte 0" to size 
    // "byte 1" to cmd, etc... 
} 

void packet_handler(PACKET_T* packet) 
{ 
    // Process the fields in a readable manner 
    if(packet->fields.size > TOO_BIG) 
    { 
     // handle error... 
    } 

    if(packet->fields.cmd == CMD_X) 
    { 
     // do stuff.. 
    } 
} 

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

+1

यह कोड काम नहीं करेगा (ज्यादातर बार) यदि निम्नलिखित कारणों से डेटा 2 अलग-अलग प्लेटफार्मों में आदान-प्रदान किया जा रहा है: 1) समाप्ति भिन्न हो सकती है। 2) संरचनाओं में पैडिंग। – Mahori

+0

@ रवि मैं एंडियननेस और पैडिंग के बारे में चिंताओं से सहमत हूं।हालांकि यह ज्ञात होना चाहिए कि मैंने इसे विशेष रूप से एम्बेडेड परियोजनाओं में उपयोग किया है। जिनमें से अधिकांश मैंने पाइप के दोनों सिरों को नियंत्रित किया। –

1

सी के शुरुआती संस्करणों में, सभी संरचना घोषणाएं फ़ील्ड का एक सामान्य सेट साझा करेंगी। यह देखते हुए:

struct x {int x_mode; int q; float x_f}; 
struct y {int y_mode; int q; int y_l}; 
struct z {int z_mode; char name[20];}; 

एक संकलक 'आकार (और संभवतः संरेखण), और संरचनाओं की एक अलग तालिका' संरचनाओं की एक तालिका के सदस्यों के नाम, प्रकार, और ऑफसेट अनिवार्य रूप से उत्पादन होगा। कंपाइलर ने ट्रैक नहीं किया कि कौन से सदस्य किस संरचना से संबंधित थे, और दो संरचनाओं को एक ही नाम के साथ सदस्य होने की अनुमति होगी, अगर टाइप और ऑफ़सेट मिलान हो (जैसे struct x और struct y के सदस्य q के साथ)। यदि पी किसी भी संरचना प्रकार के लिए सूचक था, तो पी-> क्यू पॉइंटर पी में "क्यू" का ऑफसेट जोड़ देगा और परिणामी पते से "int" लाएगा।

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

उस अंतर को भरने के लिए यूनियनों की क्षमता का एक अनिवार्य हिस्सा यह तथ्य था कि संघ के सदस्य को एक सूचक को उस सदस्य के किसी भी संघ में एक सूचक में परिवर्तित किया जा सकता है, और किसी भी संघ के सूचक को सूचक में परिवर्तित किया जा सकता है किसी भी सदस्य को। जबकि सी 8 9 मानक ने स्पष्ट रूप से यह नहीं कहा कि T* को सीधे U* पर कास्टिंग करने के लिए T और U दोनों के किसी भी यूनियन प्रकार के सूचक को कास्टिंग करने के बराबर था, और उसके बाद इसे U* पर कास्ट किया गया, बाद वाले कास्ट अनुक्रम का कोई परिभाषित व्यवहार नहीं उपयोग किए गए यूनियन प्रकार से प्रभावित होगा, और मानक ने T से U तक सीधी कास्ट के लिए किसी भी विपरीत अर्थशास्त्र को निर्दिष्ट नहीं किया है। इसके अलावा, उन मामलों में जहां एक समारोह को अज्ञात उत्पत्ति का सूचक प्राप्त हुआ, T* के माध्यम से किसी ऑब्जेक्ट को लिखने का व्यवहार T* को U* में परिवर्तित कर रहा है, और फिर U* के माध्यम से ऑब्जेक्ट को पढ़ने के प्रकार T के प्रकार के माध्यम से एक संघ लिखने के बराबर होगा और टाइप U के रूप में पढ़ना, जो कुछ मामलों में मानक परिभाषित किया जाएगा (उदाहरण के लिए आम प्रारंभिक अनुक्रम सदस्यों तक पहुंचने पर) और कार्यान्वयन-परिभाषित (अनिर्धारित के बजाए) बाकी के लिए।हालांकि कार्यक्रमों के लिए यूनियन प्रकार की वास्तविक वस्तुओं के साथ सीआईएस गारंटी का शोषण करना दुर्लभ था, लेकिन इस तथ्य का फायदा उठाने के लिए यह बहुत आम था कि अज्ञात उत्पत्ति के ऑब्जेक्ट्स के पॉइंटर्स को यूनियन सदस्यों को पॉइंटर्स की तरह व्यवहार करना था और इसके साथ जुड़े व्यवहारिक गारंटी भी थीं।

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