जवाबों:
एक संघ के साथ, आप केवल एक तत्व का उपयोग करने वाले हैं, क्योंकि वे सभी एक ही स्थान पर संग्रहीत हैं। यह तब उपयोगी होता है जब आप कुछ ऐसा स्टोर करना चाहते हैं जो कई प्रकारों में से एक हो सकता है। दूसरी ओर, एक संरचना, इसके प्रत्येक तत्व के लिए एक अलग मेमोरी स्थान है और वे सभी एक ही बार में उपयोग किए जा सकते हैं।
उनके उपयोग का एक ठोस उदाहरण देने के लिए, मैं कुछ समय पहले एक स्कीम दुभाषिया पर काम कर रहा था और मैं अनिवार्य रूप से C डेटा प्रकारों पर स्कीम डेटा प्रकारों को ओवरले कर रहा था। इसमें एक संरचना में एक संचय शामिल होता है जो उस मूल्य को संग्रहीत करने के लिए मूल्य और एक संघ के प्रकार को दर्शाता है।
union foo {
int a; // can't use both a and b at once
char b;
} foo;
struct bar {
int a; // can use both a and b simultaneously
char b;
} bar;
union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!
struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK
संपादित करें: यदि आप सोच रहे हैं कि xb को 'c' में सेट करने से xa के मान में क्या बदलाव आता है, तो तकनीकी रूप से यह अपरिभाषित है। अधिकांश आधुनिक मशीनों में एक चार बाइट होता है और एक इंट 4 बाइट्स होता है, इसलिए xb को 'c' मान देने से xa का पहला बाइट भी उसी मूल्य पर मिलता है:
union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
प्रिंट
99, 99
दो मूल्य समान क्यों हैं? क्योंकि इंट 3 के अंतिम 3 बाइट्स सभी शून्य हैं, इसलिए इसे 99 के रूप में भी पढ़ा जाता है। यदि हम xa के लिए एक बड़ी संख्या में रखते हैं, तो आप देखेंगे कि यह हमेशा ऐसा नहीं होता है:
union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
प्रिंट
387427, 99
वास्तविक स्मृति मानों पर करीब से नज़र डालने के लिए, आइए मानों को हेक्स में सेट करें और प्रिंट करें:
union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);
प्रिंट
deadbe22, 22
आप स्पष्ट रूप से देख सकते हैं कि 0x22 ने 0xEF को कहाँ से उतारा है।
परंतु
सी में, एक इंट में बाइट्स के क्रम को परिभाषित नहीं किया गया है। इस प्रोग्राम ने मेरे मैक पर 0x22 के साथ 0xEF को ओवरराइड किया, लेकिन अन्य प्लेटफ़ॉर्म हैं जहां यह 0xDE को ओवरराइट कर देगा क्योंकि बाइट्स का क्रम जो int बनाते हैं, उलटा हो गया था। इसलिए, जब कोई प्रोग्राम लिखते हैं, तो आपको संघ में विशिष्ट डेटा को अधिलेखित करने के व्यवहार पर कभी भी भरोसा नहीं करना चाहिए क्योंकि यह पोर्टेबल नहीं है।
बाइट्स के ऑर्डर पर अधिक पढ़ने के लिए, एंडियननेस की जांच करें ।
यहां संक्षिप्त उत्तर है: एक संरचना एक रिकॉर्ड संरचना है: संरचना में प्रत्येक तत्व नई जगह आवंटित करता है। तो, एक संरचना की तरह
struct foobarbazquux_t {
int foo;
long bar;
double baz;
long double quux;
}
(sizeof(int)+sizeof(long)+sizeof(double)+sizeof(long double))
प्रत्येक उदाहरण के लिए स्मृति में कम से कम बाइट्स आवंटित करता है । ("कम से कम" क्योंकि आर्किटेक्चर एलाइनमेंट की कमी कंपाइलर को स्ट्रक्चर को पैड करने के लिए मजबूर कर सकती है।)
दूसरी ओर,
union foobarbazquux_u {
int foo;
long bar;
double baz;
long double quux;
}
स्मृति का एक हिस्सा आवंटित करता है और इसे चार उपनाम देता है। तो sizeof(union foobarbazquux_u) ≥ max((sizeof(int),sizeof(long),sizeof(double),sizeof(long double))
, संरेखण के लिए कुछ अतिरिक्त की संभावना के साथ फिर से।
क्या 'संरचना' और 'संघ' के बीच अंतर बताने के लिए कोई अच्छा उदाहरण है?
एक काल्पनिक संचार प्रोटोकॉल
struct packetheader {
int sourceaddress;
int destaddress;
int messagetype;
union request {
char fourcc[4];
int requestnumber;
};
};
इस काल्पनिक प्रोटोकॉल में, यह स्पष्ट किया गया है कि "संदेश प्रकार" के आधार पर, हेडर में निम्न स्थान या तो एक अनुरोध संख्या, या चार वर्ण कोड होगा, लेकिन दोनों नहीं। संक्षेप में, यूनियनों ने एक ही भंडारण स्थान के लिए एक से अधिक डेटा प्रकार का प्रतिनिधित्व करने की अनुमति दी है, जहां यह गारंटी है कि आप केवल किसी एक समय में किसी एक प्रकार के डेटा को संग्रहीत करना चाहते हैं।
यूनियन प्रोग्रामिंग की भाषा के रूप में सी की विरासत में आधारित यूनियनों में एक निम्न स्तर का विवरण है, जहां "ओवरलैपिंग" भंडारण स्थानों को कभी-कभी इस तरह से उपयोग किया जाता है। आप कभी-कभी यादों को सहेजने के लिए यूनियनों का उपयोग कर सकते हैं जहां आपके पास एक डेटा संरचना होती है जहां एक समय में कई प्रकारों में से केवल एक को बचाया जाएगा।
सामान्य तौर पर, OS संरचित और यूनियनों की परवाह नहीं करता है और न ही जानता है - वे दोनों इसके लिए केवल मेमोरी के ब्लॉक हैं। एक मेमोरी मेमोरी का एक ब्लॉक है जो कई डेटा ऑब्जेक्ट्स को स्टोर करता है, जहां उन ऑब्जेक्ट को ओवरलैप नहीं किया जाता है। एक संघ मेमोरी का एक ब्लॉक है जो कई डेटा ऑब्जेक्ट्स को संग्रहीत करता है, लेकिन इनमें से केवल सबसे बड़ी के लिए भंडारण है, और इस प्रकार किसी भी डेटा ऑब्जेक्ट को किसी भी एक समय में स्टोर कर सकता है।
packetheader ph;
अनुरोध करने का तरीका कैसे है? ph.request.requestnumber
?
आप पहले से ही अपने सवाल में राज्य के रूप में, के बीच मुख्य अंतर union
और struct
वह यह है कि union
सदस्यों को एक दूसरे को इतना है कि एक संघ की sizeof एक है की स्मृति ओवरले, जबकि struct
सदस्यों (बीच में वैकल्पिक पैडिंग के साथ) एक दूसरे के बाद एक बाहर रखी हैं। इसके अलावा एक संघ अपने सभी सदस्यों को शामिल करने के लिए पर्याप्त है, और एक संरेखण है जो इसके सभी सदस्यों को फिट बैठता है। तो मान लें कि int
केवल 2 बाइट पतों पर संग्रहीत किया जा सकता है और 2 बाइट्स चौड़े हैं, और केवल 4 बाइट पतों पर संग्रहीत किया जा सकता है और 4 बाइट्स लंबा है। निम्नलिखित संघ
union test {
int a;
long b;
};
sizeof
4 की एक , और 4 की संरेखण आवश्यकता हो सकती है। एक संघ और एक संरचना दोनों के अंत में पैडिंग हो सकती है, लेकिन उनकी शुरुआत में नहीं। एक संरचना में लिखना केवल उस सदस्य के मान को बदलता है जिसके लिए लिखा गया है। एक संघ के सदस्य को लिखना अन्य सभी सदस्यों के मूल्य को अमान्य कर देगा। यदि आपने उन्हें पहले नहीं लिखा है, तो आप उन्हें एक्सेस नहीं कर सकते, अन्यथा व्यवहार अपरिभाषित है। जीसीसी एक विस्तार के रूप में प्रदान करता है जिसे आप वास्तव में एक संघ के सदस्यों से पढ़ सकते हैं, भले ही आपने उन्हें हाल ही में नहीं लिखा हो। ऑपरेशन सिस्टम के लिए, यह कोई फर्क नहीं पड़ता कि उपयोगकर्ता प्रोग्राम किसी यूनियन को लिखता है या किसी संरचना को। यह वास्तव में केवल संकलक का एक मुद्दा है।
संघ और संरचना की एक और महत्वपूर्ण संपत्ति है, वे अनुमति देते हैं कि उनके लिए एक संकेतक इसके किसी भी सदस्य के प्रकारों को इंगित कर सकता है । तो निम्नलिखित मान्य है:
struct test {
int a;
double b;
} * some_test_pointer;
some_test_pointer int*
या इंगित कर सकता है double*
। यदि आप टाइप test
करने का एक पता देते हैं int*
, तो यह a
वास्तव में इसके पहले सदस्य को इंगित करेगा । संघ के लिए भी यही सच है। इस प्रकार, क्योंकि एक संघ में हमेशा सही संरेखण होगा, आप किसी प्रकार को मान्य करने के लिए एक संघ का उपयोग कर सकते हैं:
union a {
int a;
double b;
};
वह संघ वास्तव में एक इंट, और एक डबल को इंगित करने में सक्षम होगा:
union a * v = (union a*)some_int_pointer;
*some_int_pointer = 5;
v->a = 10;
return *some_int_pointer;
वास्तव में मान्य है, जैसा कि C99 मानक द्वारा कहा गया है:
एक वस्तु का अपना संग्रहीत मूल्य केवल एक लैवल्यू अभिव्यक्ति द्वारा एक्सेस किया जाना चाहिए, जिसमें निम्न प्रकार हैं:
- एक प्रकार वस्तु के प्रभावी प्रकार के साथ संगत है
- ...
- एक समुच्चय या संघ प्रकार जिसमें इसके सदस्यों में पूर्वोक्त प्रकार शामिल हैं
कंपाइलर ऑप्टिमाइज़ नहीं करेगा v->a = 10;
क्योंकि यह मान को प्रभावित कर सकता है *some_int_pointer
(और फ़ंक्शन 10
इसके बजाय वापस आ जाएगा 5
)।
A union
कुछ परिदृश्यों में उपयोगी है।
union
कर्नेल के लिए डिवाइस ड्राइवर लिखने जैसे बहुत कम स्तर के हेरफेर के लिए एक उपकरण हो सकता है।
इस बात का एक उदाहरण एक चीर-फाड़ कर रहा है float
का उपयोग करके नंबर union
एक की struct
bitfields और एक साथ float
। मैं एक नंबर सेव करता हूं float
, और बाद में मैं इसके float
माध्यम से विशेष भागों तक पहुंच सकता हूं struct
। उदाहरण दिखाता है कि union
डेटा को देखने के लिए विभिन्न कोणों का उपयोग कैसे किया जाता है।
#include <stdio.h>
union foo {
struct float_guts {
unsigned int fraction : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} fg;
float f;
};
void print_float(float f) {
union foo ff;
ff.f = f;
printf("%f: %d 0x%X 0x%X\n", f, ff.fg.sign, ff.fg.exponent, ff.fg.fraction);
}
int main(){
print_float(0.15625);
return 0;
}
विकिपीडिया पर एकल सटीक विवरण पर एक नज़र डालें । मैंने वहां से उदाहरण और जादू नंबर 0.15625 का इस्तेमाल किया।
union
एक बीजीय डेटा प्रकार को लागू करने के लिए भी उपयोग किया जा सकता है जिसमें कई विकल्प होते हैं। मुझे इसका एक उदाहरण ओ'सूलीवन, स्टीवर्ट और गोएर्ज़ेन की "रियल वर्ल्ड हास्केल" पुस्तक में मिला। यह भेदभाव संघ अनुभाग में देखें।
चीयर्स!
" संघ " और " संरचना " सी भाषा के निर्माण हैं। उनके बीच "OS स्तर" अंतर की बात करना अनुचित है, क्योंकि यह कंपाइलर है जो एक या दूसरे कीवर्ड का उपयोग करने पर अलग कोड बनाता है।
गैर तकनीकी रूप से बोलने का अर्थ है:
मान: कुर्सी = मेमोरी ब्लॉक, लोग = चर
संरचना : यदि 3 लोग हैं तो वे अपने आकार के अनुसार कुर्सी पर बैठ सकते हैं।
संघ : यदि 3 लोग हैं तो बैठने के लिए केवल एक ही कुर्सी होगी, सभी को बैठने के लिए उसी कुर्सी का उपयोग करने की आवश्यकता होती है।
तकनीकी रूप से बोलने का अर्थ है:
नीचे उल्लिखित कार्यक्रम संरचना और संघ में एक साथ एक गहरा गोता देता है।
struct MAIN_STRUCT
{
UINT64 bufferaddr;
union {
UINT32 data;
struct INNER_STRUCT{
UINT16 length;
UINT8 cso;
UINT8 cmd;
} flags;
} data1;
};
बफरिंगड्र + साइज़ोफ़ (UNIT32) के लिए संघ के लिए MAIN_STRUCT आकार = sizeof (UINT64) पैडिंग के लिए 32 बिट (प्रोसेसर आर्किटेक्चर पर निर्भर करता है) = 128 बिट्स। संरचना के लिए सभी सदस्यों को आकस्मिक रूप से मेमोरी ब्लॉक मिलता है।
यूनियन को अधिकतम आकार के सदस्य (यहां इसका 32 बिट) का एक मेमोरी ब्लॉक मिलता है। संघ के अंदर एक और संरचना निहित है (INNER_STRUCT) इसके सदस्यों को कुल 32 बिट्स (16 + 8 + 8) का मेमोरी ब्लॉक मिलता है। संघ में या तो INNER_STRUCT (32 बिट) सदस्य या डेटा (32 बिट) तक पहुँचा जा सकता है।
हां, संरचना और संघ के बीच मुख्य अंतर वही है जो आपने कहा था। संरचना अपने सदस्य की सभी मेमोरी का उपयोग करती है और संघ सबसे बड़े सदस्यों की मेमोरी स्पेस का उपयोग करता है।
लेकिन सभी अंतर मेमोरी की उपयोग की आवश्यकता से निहित है। यूनियन का सबसे अच्छा उपयोग यूनिक्स की प्रक्रियाओं में देखा जा सकता है जहां हम संकेतों का उपयोग करते हैं। एक प्रक्रिया की तरह एक समय में केवल एक संकेत पर कार्य कर सकता है। तो सामान्य घोषणा होगी:
union SIGSELECT
{
SIGNAL_1 signal1;
SIGNAL_2 signal2;
.....
};
इस मामले में, प्रक्रिया सभी संकेतों की केवल उच्चतम मेमोरी का उपयोग करती है। लेकिन यदि आप इस मामले में संरचना का उपयोग करते हैं, तो स्मृति उपयोग सभी संकेतों का योग होगा। बहुत फर्क पड़ता है।
संक्षेप में, संघ का चयन किया जाना चाहिए यदि आप जानते हैं कि आप एक बार में किसी एक सदस्य का उपयोग करते हैं।
तुम्हारे पास है, बस। लेकिन इसलिए, मूल रूप से, यूनियनों की बात क्या है?
आप विभिन्न प्रकारों के समान स्थान सामग्री में रख सकते हैं। आपको यह जानना होगा कि आपने यूनियन में किस प्रकार का संग्रह किया है (इसलिए अक्सर आप इसे struct
टाइप टैग के साथ डालते हैं ...)।
यह महत्वपूर्ण क्यों है? वास्तव में अंतरिक्ष लाभ के लिए नहीं। हां, आप कुछ बिट हासिल कर सकते हैं या कुछ पैडिंग कर सकते हैं, लेकिन यह मुख्य बिंदु नहीं है।
यह प्रकार की सुरक्षा के लिए है, यह आपको कुछ प्रकार की 'डायनेमिक टाइपिंग' करने में सक्षम बनाता है: कंपाइलर जानता है कि आपकी सामग्री के अलग-अलग अर्थ हो सकते हैं और इसका सटीक अर्थ यह हो सकता है कि रन-टाइम में यह आपकी व्याख्या कैसे आपके ऊपर है। यदि आपके पास एक पॉइंटर है जो विभिन्न प्रकारों को इंगित कर सकता है, तो आपको एक संघ का उपयोग करना होगा, अन्यथा आप कोडिंग समस्या के कारण गलत हो सकते हैं (कंपाइलर खुद से कहता है "ओह, केवल यह पॉइंटर ही इस प्रकार को इंगित कर सकता है, इसलिए मैं अनुकूलन कर सकता हूं उन तक पहुँच ... ", और बुरी चीजें हो सकती हैं)।
एक संरचना इसमें सभी तत्वों के कुल आकार को आवंटित करती है।
एक संघ केवल उतना ही स्मृति आवंटित करता है जितना उसके सबसे बड़े सदस्य की आवश्यकता होती है।
संरचना और संघ के बीच अंतर क्या है?
संक्षिप्त कट उत्तर है: डिफरेंस मेमोरी आवंटन में है। स्पष्टीकरण: संरचना में, संरचना के अंदर सभी सदस्यों के लिए मेमोरी स्पेस बनाया जाएगा। यूनियन मेमोरी स्पेस में केवल उस सदस्य के लिए बनाया जाएगा जिसे सबसे बड़ी मेमोरी स्पेस की आवश्यकता होती है। निम्नलिखित कोड पर विचार करें:
struct s_tag
{
int a;
long int b;
} x;
union u_tag
{
int a;
long int b;
} y;
यहाँ संरचना और संघ के अंदर दो सदस्य हैं: int और long int। इंट के लिए मेमोरी स्पेस है: 4 बाइट और लॉन्ग इंट के लिए मेमोरी स्पेस है: 32 बिट ऑपरेटिंग सिस्टम में 8।
तो संरचना के लिए 4 + 8 = 12 बाइट्स बनाए जाएंगे, जबकि यूनियन के लिए 8 बाइट्स बनाए जाएंगे
कोड उदाहरण:
#include<stdio.h>
struct s_tag
{
int a;
long int b;
} x;
union u_tag
{
int a;
long int b;
} y;
int main()
{
printf("Memory allocation for structure = %d", sizeof(x));
printf("\nMemory allocation for union = %d", sizeof(y));
return 0;
}
रेफरी: http://www.codingpractise.com/home/c-programming/structure-and-union/
विशिष्ट प्रकार की बातचीत की आवश्यकता होने पर यूनियन यूनियनों का उपयोग अक्सर किया जाता है। संघ की उपयोगिता का अंदाजा लगाने के लिए। सी / सी मानक पुस्तकालय विशेष रूप से किसी फ़ाइल में लघु पूर्णांक लिखने के लिए डिज़ाइन किए गए फ़ंक्शन को परिभाषित नहीं करता है। Fwrite () incurs का उपयोग सरल ऑपरेशन के लिए अत्यधिक ओवरहेड को संलग्न करता है। हालांकि एक संघ का उपयोग करके आप आसानी से एक फ़ंक्शन बना सकते हैं जो एक बार में एक बाइट को एक फ़ाइल के लिए एक छोटे पूर्णांक के बाइनरी लिखते हैं। मुझे लगता है कि छोटे पूर्णांक 2 बाइट लंबे हैं
उदाहरण:
#include<stdio.h>
union pw {
short int i;
char ch[2];
};
int putw(short int num, FILE *fp);
int main (void)
{
FILE *fp;
fp fopen("test.tmp", "wb ");
putw(1000, fp); /* write the value 1000 as an integer*/
fclose(fp);
return 0;
}
int putw(short int num, FILE *fp)
{
pw word;
word.i = num;
putc(word.c[0] , fp);
return putc(word.c[1] , fp);
}
हालांकि putw () को मैंने छोटे पूर्णांक के साथ बुलाया, यह putc () और fwrite () का उपयोग करने के लिए अभ्यस्त था। लेकिन मैं एक उदाहरण दिखाना चाहता था कि कैसे संघ का इस्तेमाल किया जा सकता है
संरचना विभिन्न डेटा प्रकारों का संग्रह है जहां विभिन्न प्रकार के डेटा इसमें निवास कर सकते हैं और हर एक को मेमोरी का अपना ब्लॉक मिलता है
हम आम तौर पर संघ का उपयोग करते हैं जब हम यह सुनिश्चित करते हैं कि केवल एक ही चर का उपयोग एक बार में किया जाएगा और आप वर्तमान मेमोरी का पूरी तरह से उपयोग करना चाहते हैं क्योंकि यह केवल एक ही मेमोरी का ब्लॉक प्राप्त करता है जो सबसे बड़े प्रकार के बराबर है।
struct emp
{
char x;//1 byte
float y; //4 byte
} e;
कुल मेमोरी यह = = 5 बाइट
union emp
{
char x;//1 byte
float y; //4 byte
} e;
कुल मेमोरी इसे = 4 बाइट मिलती है
बाइट ऑर्डर करने वाले फंक्शन को लिखते समय यूनियनें काम आती हैं जो नीचे दी गई हैं। यह संरचना के साथ संभव नहीं है।
int main(int argc, char **argv) {
union {
short s;
char c[sizeof(short)];
} un;
un.s = 0x0102;
if (sizeof(short) == 2) {
if (un.c[0] == 1 && un.c[1] == 2)
printf("big-endian\n");
else if (un.c[0] == 2 && un.c[1] == 1)
printf("little-endian\n");
else
printf("unknown\n");
} else
printf("sizeof(short) = %d\n", sizeof(short));
exit(0);
}
// Program from Unix Network Programming Vol. 1 by Stevens.
एक संघ एक संरचना से अलग है क्योंकि एक संघ दूसरों पर दोहराता है: यह एक ही स्मृति को फिर से परिभाषित करता है जबकि संरचना एक के बाद एक ओवरलैप या पुनर्परिभाषित के साथ परिभाषित करती है।