मैंने क्या बनाया=i+++1; C++ 17 में कानूनी?




language-lawyer c++17 (2)

आपने नए वाक्य की पहचान की

दाएं ऑपरेंड को बाएं ऑपेंड से पहले अनुक्रमित किया जाता है।

और आपने सही पहचाना कि लेवल के रूप में लेफ्ट ऑपरेंड का मूल्यांकन अप्रासंगिक है। हालाँकि, इससे पहले अनुक्रमित होना एक सकर्मक संबंध होना निर्दिष्ट है। पूर्ण अधिकार ऑपरेंड (पोस्ट-इन्क्रीमेंट सहित) इसलिए असाइनमेंट से पहले भी अनुक्रमित है। C ++ 11 में, असाइनमेंट से पहले केवल सही ऑपरेंड का मान गणना किया गया था।

इससे पहले कि आप अपरिभाषित व्यवहार शुरू करें, यह स्पष्ट रूप से N4659 (C ++ 17) में सूचीबद्ध है।

  i = i++ + 1;        // the value of i is incremented

फिर भी N3337 (C ++ 11) में

  i = i++ + 1;        // the behavior is undefined

किया बदल गया?

मैं [N4659 basic.exec] से क्या इकट्ठा कर सकता हूं

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

जहां मूल्य को [N4659 basic.type] पर परिभाषित किया गया है

तुच्छ रूप से कॉपी करने योग्य प्रकारों के लिए, मूल्य प्रतिनिधित्व वस्तु प्रतिनिधित्व में बिट्स का एक सेट है जो एक मूल्य निर्धारित करता है, जो मूल्यों के कार्यान्वयन-परिभाषित सेट का एक असतत तत्व है

[N3337 basic.exec] से

जहां नोट किया गया है, सिवाय इसके कि अलग-अलग संचालकों के संचालनों का मूल्यांकन और अलग-अलग अभिव्यक्तियों के उप-वर्गों का मूल्यांकन न किया जाए। [...] एक ऑपरेटर के ऑपरेंड्स के मूल्य गणना ऑपरेटर के परिणाम के मूल्य गणना से पहले अनुक्रमित किए जाते हैं। यदि एक स्केलर ऑब्जेक्ट पर एक साइड इफेक्ट एक समान स्केलर ऑब्जेक्ट पर या तो एक साइड इफेक्ट या एक ही स्केलर ऑब्जेक्ट के मूल्य का उपयोग करते हुए एक मूल्य गणना के सापेक्ष अप्रभावित है, तो व्यवहार अपरिभाषित है।

इसी तरह, मूल्य को [N3337 basic.type] पर परिभाषित किया गया है

तुच्छ रूप से प्रतिलिपि योग्य प्रकारों के लिए, मूल्य प्रतिनिधित्व वस्तु प्रतिनिधित्व में बिट्स का एक सेट है जो एक मूल्य निर्धारित करता है, जो मूल्यों के कार्यान्वयन-परिभाषित सेट का एक असतत तत्व है।

वे समरूपता का उल्लेख करने के लिए समान हैं जो कोई फर्क नहीं पड़ता, और स्केलर ऑब्जेक्ट के बजाय मेमोरी लोकेशन के उपयोग के साथ, जहां

अंकगणित प्रकार, गणना प्रकार, सूचक प्रकार, सदस्य प्रकारों के सूचक, std::nullptr_t , और इन प्रकारों के std::nullptr_t योग्य संस्करणों को सामूहिक रूप से स्केलर प्रकार कहा जाता है।

जो उदाहरण को प्रभावित नहीं करता है।

[N4659 expr.ass] से

असाइनमेंट ऑपरेटर (=) और कंपाउंड असाइनमेंट ऑपरेटर सभी ग्रुप को राइट-टू-लेफ्ट करते हैं। सभी को अपने बाएं ऑपरेंड के रूप में एक परिवर्तनीय अंतराल की आवश्यकता होती है और बाएं ऑपरेंड का जिक्र करते हुए एक अंतराल लौटाता है। सभी मामलों में परिणाम एक बिट-फ़ील्ड है यदि बाएं ऑपरेंड थोड़ा-फ़ील्ड है। सभी मामलों में, असाइनमेंट को दाएं और बाएं ऑपरेंड्स के मूल्य गणना के बाद, और असाइनमेंट अभिव्यक्ति के मूल्य गणना से पहले अनुक्रमित किया जाता है। दाएं ऑपरेंड को बाएं ऑपेंड से पहले अनुक्रमित किया जाता है।

[N3337 expr.ass] से

असाइनमेंट ऑपरेटर (=) और कंपाउंड असाइनमेंट ऑपरेटर सभी ग्रुप को राइट-टू-लेफ्ट करते हैं। सभी को अपने बाएं ऑपरेंड के रूप में एक परिवर्तनीय अंतराल की आवश्यकता होती है और बाएं ऑपरेंड का जिक्र करते हुए एक अंतराल लौटाता है। सभी मामलों में परिणाम एक बिट-फ़ील्ड है यदि बाएं ऑपरेंड थोड़ा-फ़ील्ड है। सभी मामलों में, असाइनमेंट को दाएं और बाएं ऑपरेंड्स के मूल्य गणना के बाद, और असाइनमेंट अभिव्यक्ति के मूल्य गणना से पहले अनुक्रमित किया जाता है।

N3337 में अंतिम वाक्य अनुपस्थित होने का एकमात्र अंतर है।

हालांकि अंतिम वाक्य, का कोई महत्व नहीं होना चाहिए क्योंकि बाएं ऑपरेंड i न तो "एक और साइड इफेक्ट" है और न ही "समान स्केलर ऑब्जेक्ट के मूल्य का उपयोग" के रूप में आईडी-एक्सप्रेशन एक अंतराल है।


पुराने C ++ मानकों और C11 में, असाइनमेंट ऑपरेटर टेक्स्ट की परिभाषा टेक्स्ट के साथ समाप्त होती है:

ऑपरेंड का मूल्यांकन अप्राप्त है।

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

यह पाठ केवल C ++ 11 में हटा दिया गया था, जिससे यह कुछ अस्पष्ट हो गया। यह यूबी है या नहीं है? यह C ++ 17 में स्पष्ट किया गया है जहां उन्होंने जोड़ा:

दाएं ऑपरेंड को बाएं ऑपेंड से पहले अनुक्रमित किया जाता है।

एक साइड नोट के रूप में, यहां तक ​​कि पुराने मानकों में, यह सब बहुत स्पष्ट किया गया था, उदाहरण के लिए C99:

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

मूल रूप से, C11 / C ++ 11 में, उन्होंने इस पाठ को हटाते समय गड़बड़ कर दी।







c++17