10

The C++11 standard (5.17, expr.ass) में एक अभिव्यक्ति में एक ही चर का काम कहा गया है किडबल सी ++ 11

सभी मामलों में, काम मूल्य गणना के बाद अनुक्रम है सही के और बाएं ऑपरेंड, और असाइनमेंट अभिव्यक्ति की मान गणना के पहले। एक धुंधलेपन-अनुक्रम समारोह कॉल करने के लिए सम्मान के साथ, एक यौगिक काम के संचालन के लिए एक एकल मूल्यांकन

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

दिया कोड होगा:

int a = 0; 
a = (a+=1) = 10; 

if (a == 10) { 
    printf("this is defined"); 
} else { 
    printf("undefined"); 
} 

हमेशा a==10 का मूल्यांकन?

+0

साइड ध्यान दें: एक संभवतः अपरिभाषित अभिव्यक्ति हमें बताओ नहीं पड़ता कि यह वास्तव में यूबी है या नहीं का परिणाम जाँच हो रही है। यह यूबी हो सकता है और सही परिणाम उत्पन्न कर सकता है। – jrok

+3

@jrok यह एक नमूना कोड है, शायद एक एसएससीसीई भी, क्योंकि एसओ को मुझे * वैध कोड * शामिल करने की आवश्यकता है। मैंने जिज्ञासा से बाहर परीक्षण करने का प्रयास किया, लेकिन मुझे एहसास हुआ कि यह कुछ भी साबित नहीं करता है; इसलिए मैंने इसका भी उल्लेख नहीं किया। – Dariusz

+2

@jrok - यह "सही" परिणाम उत्पन्न कर सकता है। उद्धरण महत्वपूर्ण हैं। ''

उत्तर

6

के अपने कोड को फिर से लिखने के रूप में

E1 = (E2 = E3) 

जहां ई 1 अभिव्यक्ति a है, E2 अभिव्यक्ति a += 1 है और E3 अभिव्यक्ति 10 में है। यहाँ हम ussed, कि असाइनमेंट ऑपरेटर समूहों दाएँ-से-बाएँ (§5.17/1 सी ++ 11 स्टैंडर्ड में)।

§5.17/1 इसके अलावा राज्यों:

सभी मामलों में, काम काम अभिव्यक्ति के मूल्य गणना से पहले दाएं और बाएं ऑपरेंड के मूल्य गणना के बाद अनुक्रम है, और।

हमारे अभिव्यक्ति को यह लागू करने का मतलब है कि हम पहले subexpressions E1 और E2 = E3 मूल्यांकन करना चाहिए। नोट नहीं "अनुक्रम-से पहले" इन दोनों के मूल्यांकन के बीच संबंधों को वहाँ है, लेकिन है कि कोई समस्याओं का कारण बनता है।

आईडी अभिव्यक्तिE1 के मूल्यांकन तुच्छ है (परिणाम a ही है)। असाइनमेंट-अभिव्यक्ति का मूल्यांकनE2 = E3 निम्नानुसार प्राप्त होता है:

पहले दोनों उप-अभिव्यक्तियों का मूल्यांकन किया जाना चाहिए। शाब्दिकE3 के मूल्यांकन (मूल्य 10 का एक prvalue देता है) फिर से तुच्छ है।

(मिश्रित) के मूल्यांकन काम अभिव्यक्तिE2 निम्न चरणों में किया जाता है:

1) a += 1 के व्यवहार a = a + 1 के बराबर है लेकिन a केवल एक बार मूल्यांकन किया जाता है (§5.17/7) । subexpressions a और 1 (एक मनमाना क्रम में), एक lvalue करने वाली rvalue रूपांतरण आदेश a में संग्रहीत मूल्य को पढ़ने के लिए में a लिए आवेदन किया है मूल्यांकन करने के बाद।

2) a के मूल्यों (जो 0 है) और 1 के लिए जोड़ रहे हैं (a + 1) और इस के अलावा का परिणाम मूल्य 1 के prvalue है।

3) इससे पहले कि हम काम a = a + 1 बाईं संकार्य संदर्भित करता है वस्तु के मूल्य का परिणाम गणना कर सकता है सही संकार्य (§5.17/2) के मान से बदल दिया गया है। E2 का परिणाम तो एक lvalue नया मान 1 को refereing है।ध्यान दें कि साइड इफेक्ट (बाएं ऑपरेंड के मान को अपडेट करना) असाइनमेंट अभिव्यक्ति की मान गणना से पहले अनुक्रमित किया गया है। यह ऊपर उल्लिखित §5.17/1 है।

अब जब हम subexpressions E2 और E3 का मूल्यांकन किया है, अभिव्यक्ति E2 का मूल्य E3 का मूल्य है, जो 10 है की जगह को दर्शाता है। इसलिए E2 = E3 का परिणाम मूल्य 10 का एक लाभा है।

अंत में, मूल्य अभिव्यक्ति E1 को E2 = E3 अभिव्यक्ति के मान से प्रतिस्थापित किया गया है, जिसे हम 10 मानते हैं। इस प्रकार, परिवर्तनीय a मान 10 मानने के लिए समाप्त होता है।

चूंकि ये सभी चरण अच्छी तरह परिभाषित हैं, इसलिए संपूर्ण अभिव्यक्ति एक अच्छी तरह परिभाषित मान उत्पन्न करती है।

7

हां, सी ++ 98 और सी ++ 11 के बीच कोई बदलाव आया था। मेरा मानना ​​है कि आपका उदाहरण सी ++ 11 नियमों के तहत अच्छी तरह से परिभाषित किया जाना चाहिए, जबकि सी ++ 98 नियमों के तहत अपरिभाषित व्यवहार प्रदर्शित करना।

एक सरल उदाहरण के रूप में, x = ++x; सी ++ 98 में अपरिभाषित है लेकिन सी ++ 11 में अच्छी तरह परिभाषित है। ध्यान दें कि x = x++; अभी भी अनिर्धारित है (पोस्ट-वृद्धि का दुष्प्रभाव अभिव्यक्ति के मूल्यांकन के साथ नहीं है, जबकि पूर्व-वृद्धि के साइड इफेक्ट को उसके समक्ष अनुक्रमित किया गया है)।

+0

यह दिलचस्प और पता करने के लिए अच्छा है, हालांकि आप दुर्भाग्य कोड पोस्ट का पता नहीं। आप इसे अपरिभाषित/अनिर्दिष्ट व्यवहार होने के बारे में कोई विचार है? – Dariusz

+0

मेरा मानना ​​है कि अपने उदाहरण अच्छी तरह से परिभाषित किया गया है। तदनुसार जवाब अपडेट किया गया। –

3

थोड़ा सा शोध करने के बाद, मुझे विश्वास है कि आपके कोड व्यवहार को C++ 11 में अच्छी तरह से परिभाषित किया गया है।

$ 1,9/15 राज्यों:

एक ऑपरेटर की ऑपरेंड के मूल्य संगणना से पहले ऑपरेटर के परिणाम का मूल्य गणना अनुक्रम कर रहे हैं।

$ 5,17/1 कहता है:

असाइनमेंट ऑपरेटर (=) और मिश्रित असाइनमेंट ऑपरेटर सभी समूह दाएँ-से-बाएँ।

अगर मैं सही ढंग से समझ, अपने उदाहरण में

a = (a+=1) = 10; 

यह संकेत मिलता है की इस अभिव्यक्ति के लिए है (a+=1) = 10 का मूल्य गणना और मूल्य गणना से पहले किया जा करने के लिए है कि (a+=1) और 10 का मूल्य संगणना a = (a+=1) = 10; से पहले समाप्त हो गया है मूल्यांकन किया गया है।

$ 5,17/1 कहता है:

सभी मामलों में, काम दाएं और बाएं ऑपरेंड के मूल्य गणना के बाद अनुक्रम, और काम अभिव्यक्ति के मूल्य गणना से पहले किया गया है।

इसका मतलब है कि काम संक्रामिता की वजह से, मूल्य गणना से पहले होना चाहिए, और इसलिए, (a+=1) = 10 के मूल्यांकन केवल काम a+=1 के बाद शुरू कर सकते हैं (अपने मूल्य केवल पक्ष प्रभाव के बाद की गणना की जा सकती है क्योंकि)।

ही दूसरे और तीसरे कार्य के लिए सच है।

भी देखें इस excellent answer, जो जिस तरह से बेहतर और अधिक विस्तार से अनुक्रम से पहले संबंध और बताते हैं की तुलना में मैं कर सकता।