C ++ अनाम संरचनाओं को अस्वीकार क्यों करता है?


92

कुछ C ++ कंपाइलर अनाम यूनियनों और स्ट्रक्चर्स को मानक C ++ के विस्तार के रूप में अनुमति देते हैं। यह थोड़ा-बहुत चीनी है जो कभी-कभी बहुत मददगार होता है।

तर्क क्या है जो इसे मानक का हिस्सा होने से रोकता है? क्या कोई तकनीकी अवरोध है? एक दार्शनिक? या सिर्फ इसे सही ठहराने की जरूरत नहीं है?

यहाँ एक नमूना है जो मैं बात कर रहा हूँ:

struct vector3 {
  union {
    struct {
      float x;
      float y;
      float z;
    };
    float v[3];
  };
};

मेरा संकलक इसे स्वीकार करेगा, लेकिन यह चेतावनी देता है कि "नामहीन संरचना / संघ" C ++ के लिए एक गैर-मानक विस्तार है


3
स्पष्ट रूप से आपके मतलब के बारे में कुछ भ्रम है। क्या आप कृपया एक कोड का उदाहरण प्रदान कर सकते हैं जो केवल संकलक विस्तार के कारण संकलित करता है?
राब केनेडी

72
ध्यान दें कि दो अवधारणाएँ हैं, जो समान हैं, लेकिन बहुत भिन्न हैं: अनाम संरचनाएं और अनाम संरचनाएं । पहला यह है, जो C ++ का समर्थन करता है: struct { int i; } a; a.i = 0;(प्रकार का कोई नाम नहीं है)। दूसरा यह एक है, जिसे C ++ समर्थन नहीं करता है: struct { int i; }; i = 0;(प्रकार का कोई नाम नहीं है, और यह आसपास के दायरे में बच जाता है)। C ++, हालांकि, अनाम और अनाम दोनों यूनियनों का समर्थन करता है
जोहान्स स्काउब -

यह बल्कि दिलचस्प VMMLib वेक्टर लाइब्रेरी जैसा दिखता है। मेरा मानना ​​है कि समस्या यह है कि संघ में एक अनाम संरचना शामिल है, लेकिन मैं अनिश्चित हूं।
ग्रेफेड

1
FWIW यह "एनोनिमस" है, न कि "अनाम", और यूनियनों का समर्थन है जैसा कि लिटब कहते हैं। stackoverflow.com/q/14248044/560648
कक्षा में हल्की दौड़

1
@AdrianMcCarthy: यह ठीक है (FSVO "फाइन"; पेसकी कंपाइलर क्रिप्टोकरंसी), लेकिन ठीक है "अनाम" एक असंबंधित, मानक अवधारणा है।
को ऑर्बिट में

जवाबों:


50

जैसा कि अन्य ने बताया है कि मानक सी ++ में अनाम यूनियनों की अनुमति है, लेकिन अनाम संरचनाएं नहीं हैं।

इसका कारण यह है कि C अनाम यूनियनों का समर्थन करता है लेकिन अनाम संरचनाओं का नहीं *, इसलिए C ++ संगतता के लिए पूर्व का समर्थन करता है लेकिन उत्तरार्द्ध का नहीं क्योंकि यह संगतता के लिए आवश्यक नहीं है।

इसके अलावा, C ++ में अनाम संरचनाओं का बहुत उपयोग नहीं है। आपके द्वारा उपयोग की जाने वाली संरचना में तीन फ़्लैट वाली संरचना होती है .v[i], जिसे या तो इसके द्वारा संदर्भित किया जा सकता है , या.x , .yऔर .z++, मैं सी में अपरिभाषित व्यवहार में परिणाम विश्वास करते हैं। C ++ आपको एक संघ के एक सदस्य को लिखने की अनुमति नहीं देता है, कहो .v[1]और फिर किसी अन्य सदस्य से पढ़ो, कहो.y । हालाँकि ऐसा करने वाला कोड असामान्य नहीं है लेकिन यह वास्तव में अच्छी तरह से परिभाषित नहीं है।

उपयोगकर्ता-परिभाषित प्रकारों के लिए C ++ की सुविधाएं वैकल्पिक समाधान प्रदान करती हैं। उदाहरण के लिए:

struct vector3 {
  float v[3];
  float &operator[] (int i) { return v[i]; }
  float &x() { return v[0]; }
  float &y() { return v[1]; }
  float &z() { return v[2]; }
};

* C11 जाहिरा तौर पर अनाम संरचनाओं को जोड़ता है, इसलिए C ++ में भविष्य का संशोधन उन्हें जोड़ सकता है।


2
+1: मेरा उदाहरण C ++ में अपरिभाषित व्यवहार पर निर्भर करता है - जब मैंने प्रश्न लिखा था तो कुछ मुझे वापस पता नहीं था।
एड्रियन मैक्कार्थी

2
"C ++ आपको एक संघ के एक सदस्य को लिखने की अनुमति नहीं देता [...] और फिर किसी अन्य सदस्य से पढ़ता है" - जब तक कि सदस्य मानक-लेआउट ऑब्जेक्ट नहीं हैं और अपने स्वयं के सदस्यों का एक सामान्य प्रारंभिक अनुक्रम साझा करते हैं, और आप ' पुनः अपने सदस्यों को सामान्य प्रारंभिक अनुक्रम के भीतर लिखना / पढ़ना । यही कारण है कि है की अनुमति दी (यानी परिभाषित)।
अंडरस्कोर_ड

5
@underscore_d: हाँ, यदि प्रकार एक सामान्य प्रारंभिक अनुक्रम के साथ मानक लेआउट हैं। हालांकि, एक संरचना इस तरह से एक सरणी के साथ कभी भी उपनाम नहीं कर सकती है , क्योंकि सी ++ की "सामान्य प्रारंभिक अनुक्रम" नियम बताते हैं कि एक सामान्य प्रारंभिक अनुक्रम केवल संरचनाओं के बीच हो सकता है । ऐरे का उल्लेख नहीं किया गया है, इसलिए वे इस तरह से उपनाम नहीं दे सकते हैं।
निकोल बोलस

@ निचलोलस ओह, हाहा - मेरा विश्वास करो - मैंने कई बार चाहा है कि इस भत्ते में एरे और अन्य प्राइमिटिव शामिल थे! लेकिन मैंने उस पर संभावित व्यावहारिक सीमाओं के बारे में ज्यादा नहीं सोचा है, इसलिए शायद यह उतना सरल नहीं है जितना कि वर्तमान में लगता है। मेरी टिप्पणी अधिक सामान्य थी, लेकिन हो सकता है कि मुझे लगता है कि सरणियों को इसमें शामिल करने से चूक का खतरा था, इसलिए इसे जोड़ने के लिए धन्यवाद।
अंडरस्कोर_ड

"इसका कारण यह है कि सी गुमनाम यूनियनों का समर्थन करता है लेकिन अनाम संरचनाओं का नहीं" - नहीं। आपका फुटनोट स्पष्ट करता है कि आप C99 के बारे में या इससे पहले यहां बात कर रहे थे। "अनाम संघ" शब्द C99 मानक में कहीं भी प्रकट नहीं होता है। GCC एक डायग्नोस्टिक (-std = c99-upantic ऑप्शंस) में दावा करता है कि "ISO C99 अनाम संरचनाओं / यूनियनों का समर्थन नहीं करता है"। अनाम बिट-फ़ील्ड के अलावा अन्य अनाम सदस्यों के बारे में मानक कुछ भी उल्लेख नहीं करता है। मुझे पूरी तरह से यकीन नहीं है कि अगर संरचना-घोषणाएं घोषणाएं हैं, लेकिन अगर वे हैं, तो अनाम यूनियनों को 6.7p2 प्रति सबसे अच्छा अपरिभाषित उल्लंघन है।

21

मैं कहता हूँ, तुम vector3सिर्फ एक का उपयोग करके अपनी घोषणा को साफ कर सकते हैंunion

union vector3 {
  struct { float x, y, z; } ;
  float v[3] ;
} ;

बेशक, गुमनाम संरचनाओं था एक MSVC विस्तार । लेकिन आईएसओ सी 11 अब इसकी अनुमति देता है , और जीसीसी इसे अनुमति देता है , और इसलिए Apple का llvm संकलक करता है।

C11 और C ++ 11 में क्यों नहीं? मुझे यकीन नहीं है, लेकिन व्यावहारिक रूप से सबसे कह (gcc ++, MSVC ++ और Apple के C ++ कंपाइलर) C ++ कंपाइलर उनका समर्थन करते हैं।


1
अद्यतन जानकारी के लिए +1। मेरे पास एक बाहरी संरचना होने का कारण यह था कि "वास्तविक कोड" के तरीके भी थे।
एड्रियन मैकार्थी

केवल एक चीज जो आप एक संघ के साथ नहीं कर सकते हैं वे स्थिर डेटा सदस्य हैं, या वंशानुक्रम का उपयोग करते हैं
बोब्बोबो

2
धन्यवाद। मैं एक संघ या वर्ग की तरह कभी भी नया नहीं हो सकता।
एड्रियन मैकार्थी

मुझे पता है कि सन स्टूडियो ने डिफ़ॉल्ट रूप से C ++ 11 से पहले अनाम संरचना का समर्थन नहीं किया था। यदि आप क्रॉस प्लेटफ़ॉर्म कोड लिख रहे हैं और कंपाइलर C + 11 में अपग्रेड नहीं हुए हैं तो अनाम संरचना का उपयोग न करें।
आईरिस

6

पक्का नहीं आपका क्या मतलब है। C ++ की धारा 9.5, खंड 2:

रूप का एक संघ

union { member-specification } ;

एक गुमनाम संघ कहा जाता है; यह अनाम प्रकार की अनाम वस्तु को परिभाषित करता है।

आप इस तरह की चीजें भी कर सकते हैं:

void foo()
{
  typedef
  struct { // unnamed, is that what you mean by anonymous?
    int a;
    char b;
  } MyStructType; // this is more of a "C" style, but valid C++ nonetheless

  struct { // an anonymous struct, not even typedef'd
    double x;
    double y;
  } point = { 1.0, 3.4 };
}

हमेशा बहुत उपयोगी नहीं ... हालांकि कभी-कभी गंदा मैक्रो परिभाषाओं में उपयोगी होता है।


11
-1 क्योंकि यह कह रहा है कि यह एक अनाम संरचना को परिभाषित करता है। प्रश्न के ऊपर टिप्पणी देखें - आप एक अनाम संरचना को परिभाषित कर रहे हैं, एक अनाम नहीं।
जोहान्स शाउब -

1

यूनियनें गुमनाम हो सकती हैं; मानक देखें, 9.5 पैरा 2।

अनाम उद्देश्य या वर्ग को पूरा करने के लिए आप किस उद्देश्य से देखते हैं? यह अनुमान लगाने से पहले कि कुछ मानक में क्यों नहीं है, मैं कुछ विचार करना चाहूंगा कि यह क्यों होना चाहिए, और मुझे एक अनाम संरचना के लिए उपयोग नहीं दिखता है।


1

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


1
अनाम संरचना / यूनियनों को बनाने के तरीके के कारण (यह विशेष, इनलाइन सिंटैक्स है जिसे किसी मैक्रो को छोड़कर छिपाया नहीं जा सकता है) आपको आश्चर्य नहीं हो सकता है कि आप जिस सदस्य का उपयोग कर रहे हैं वह अनाम सदस्य है। इसलिए मुझे नहीं लगता कि इस तर्क का कोई मतलब है। वास्तविक कारण यह है कि सी यूनियनों को सी ++ में समर्थन दिया जाता है, केवल सी अनुकूलता के लिए। C अनाम संरचनाओं का समर्थन नहीं करता (C11 तक) और इसलिए C ++ या तो नहीं करता है।
bames53

1

तुम्हारा कोड

union {
  struct {
    float x;
    float y;
    float z;
  };
  float v[3];
};

के समान ही

union Foo {
   int;
   float v[3];
};

जो निश्चित रूप से अमान्य है (C99 और उससे पहले)।

कारण शायद पार्सिंग को सरल बनाना है (सी में), क्योंकि उस स्थिति में आपको केवल यह जांचने की आवश्यकता है कि संरचना / संघ निकाय में केवल "घोषणाकर्ता कथन" हैं

Type field;

कहा कि, gcc और "अन्य संकलक" एक विस्तार के रूप में अनाम फ़ील्ड का समर्थन करते हैं।

संपादित करें: अनाम संरचना अब C11 (.76.7.2.1 / 13) में आधिकारिक तौर पर समर्थित हैं।


5
पार्सिंग के नजरिए से, मुझे नहीं लगता कि union { ... }यह किसी भी तरह से अलग है struct { ... }। पूर्व वैध है, लेकिन बाद वाला नहीं है।
जोहान्स शहाब -

3
यह देखते हुए कि सामान्य रूप से सी + + कितना मुश्किल है, मुझे लगता है कि मानक के अनुसार अनाम संरचना और यूनियनों को बंद किए गए मानक को केवल पार्सिंग को सरल बनाने में संदेह है।
एड्रियन मैक्कार्थी

@ एड्रियन: मैंने कहा सी, सी ++ नहीं। C ++ C के सिंटैक्स को अपनाता है और इसे विस्तारित करता है। संभवतः C ++ के रचनाकारों को अनाम संरचना / संघ के सदस्यों को अनुमति देने की आवश्यकता नहीं है, ताकि वे वाक्य रचना के उस हिस्से के साथ गड़बड़ न करें।
kennytm

@ एड्रियन, गुड प्वाइंट द एड्रियन, मैंने हमेशा नहीं सोचा था कि "लागू करने के लिए बहुत कठिन" कभी
बंजारे

C और C ++ दोनों अनाम यूनियनों का समर्थन करते हैं, इसलिए जो टिप्पणी union { ... };अमान्य है वह सही नहीं है।
bames53
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.