अपरिभाषित व्यवहार और अनुक्रम अंक


986

"अनुक्रम बिंदु" क्या हैं?

अपरिभाषित व्यवहार और अनुक्रम बिंदुओं के बीच क्या संबंध है?

मैं अक्सर a[++i] = i;अपने आप को बेहतर महसूस करने के लिए, मजाकिया और जटिल जैसे भावों का उपयोग करता हूं। मुझे उनका उपयोग क्यों रोकना चाहिए?

यदि आपने इसे पढ़ा है, तो निश्चित रूप से अनुवर्ती व्यवहार और अनुक्रम बिंदुओं को लोड किए गए अनुवर्ती प्रश्न पर जाना सुनिश्चित करें ।

(नोट: यह स्टैक ओवरफ्लो के C ++ FAQ के लिए एक प्रविष्टि माना जाता है । यदि आप इस रूप में एक FAQ प्रदान करने के विचार की आलोचना करना चाहते हैं, तो मेटा पर पोस्टिंग जो यह सब शुरू करती है वह करने के लिए जगह होगी। उत्तर) उस प्रश्न की निगरानी C ++ चैट रूम में की जाती है , जहाँ पहली बार में FAQ विचार शुरू हुआ है, इसलिए आपका उत्तर उन लोगों द्वारा पढ़ा जा सकता है, जो विचार के साथ आए थे।)

जवाबों:


682

सी ++ 98 और सी ++ 03

यह उत्तर C ++ मानक के पुराने संस्करणों के लिए है। मानक के C ++ 11 और C ++ 14 संस्करणों में औपचारिक रूप से 'अनुक्रम बिंदु' नहीं हैं; इसके बजाय 'अनुक्रमित' या 'निष्कासित' या 'अनिश्चित अनुक्रमण' से पहले संचालन किया जाता है। शुद्ध प्रभाव अनिवार्य रूप से एक ही है, लेकिन शब्दावली अलग है।


अस्वीकरण : ठीक है। यह उत्तर थोड़ा लंबा है। इसलिए इसे पढ़ते समय धैर्य रखें। यदि आप पहले से ही इन चीजों को जानते हैं, तो उन्हें फिर से पढ़ना आपको पागल नहीं करेगा।

पूर्व-आवश्यकताएं : C ++ मानक का एक प्राथमिक ज्ञान


अनुक्रम अंक क्या हैं?

मानक कहते हैं

निष्पादन बिंदुओं में कुछ निर्दिष्ट बिंदुओं पर अनुक्रम बिंदु कहा जाता है , पिछले मूल्यांकन के सभी दुष्प्रभाव पूर्ण होंगे और बाद के मूल्यांकन के कोई दुष्प्रभाव नहीं हुए होंगे। (§1.9 / 7)

दुष्प्रभाव? साइड इफेक्ट्स क्या हैं?

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

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

int x = y++; //where y is also an int

इनिशियलाइज़ेशन ऑपरेशन के अलावा ऑपरेटर yके साइड इफेक्ट के कारण मूल्य में परिवर्तन होता है ++

अब तक सब ठीक है। अनुक्रम बिंदुओं पर आगे बढ़ना। Comp.lang.c लेखक द्वारा दिए गए seq-points की एक वैकल्पिक परिभाषा Steve Summit:

अनुक्रम बिंदु समय का एक बिंदु है जिस पर धूल जम गई है और अब तक देखे गए सभी दुष्प्रभाव पूर्ण होने की गारंटी है।


C ++ मानक में सूचीबद्ध सामान्य अनुक्रम बिंदु क्या हैं?

वो है:

  • पूर्ण अभिव्यक्ति (के मूल्यांकन के अंत में §1.9/16) (एक पूर्ण अभिव्यक्ति एक अभिव्यक्ति है कि एक और अभिव्यक्ति का एक उपसूचक नहीं है।) 1

    उदाहरण :

    int a = 5; // ; is a sequence point here
  • पहली अभिव्यक्ति के मूल्यांकन के बाद निम्न में से प्रत्येक के मूल्यांकन में ( 2§1.9/18 )

    • a && b (§5.14)
    • a || b (§5.15)
    • a ? b : c (§5.16)
    • a , b (§5.18)(यहां a, b एक अल्पविराम ऑपरेटर है; अल्पविराम ऑपरेटर func(a,a++) ,नहीं है, यह केवल तर्कों के बीच एक विभाजक है aऔर a++इस प्रकार व्यवहार उस मामले में अपरिभाषित है (यदि aइसे एक आदिम प्रकार माना जाता है)।
  • फ़ंक्शन कॉल में (फ़ंक्शन या इनलाइन है या नहीं), फ़ंक्शन फ़ंक्शन के सभी फ़ंक्शन तर्कों (यदि कोई है) के मूल्यांकन के बाद होता है, जो फ़ंक्शन बॉडी में किसी भी अभिव्यक्ति या स्टेटमेंट के निष्पादन से पहले होता है ( §1.9/17)।

1: नोट: एक पूर्ण-अभिव्यक्ति के मूल्यांकन में उप-अभिव्यक्ति के मूल्यांकन शामिल हो सकते हैं जो पूर्ण-अभिव्यक्ति का शाब्दिक हिस्सा नहीं हैं। उदाहरण के लिए, डिफ़ॉल्ट तर्क अभिव्यक्तियों (8.3.6) के मूल्यांकन में शामिल उप-अभिव्यक्तियों को उस फ़ंक्शन में बनाया जाना माना जाता है, जो फ़ंक्शन को कॉल करता है, न कि अभिव्यक्ति जो डिफ़ॉल्ट तर्क को परिभाषित करता है

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


अपरिभाषित व्यवहार क्या है?

स्टैंडर्ड धारा में अपरिभाषित व्यवहार को परिभाषित करता है §1.3.12के रूप में

व्यवहार, जैसे कि एक गलत प्रोग्राम निर्माण या गलत डेटा के उपयोग पर उत्पन्न हो सकता है, जिसके लिए यह अंतर्राष्ट्रीय मानक 3 आवश्यकताओं को लागू नहीं करता है

जब यह अंतर्राष्ट्रीय मानक व्यवहार की किसी भी स्पष्ट परिभाषा के विवरण को छोड़ देता है, तो अपरिभाषित व्यवहार की भी उम्मीद की जा सकती है।

3: स्थिति पूरी तरह से, अप्रत्याशित परिणामों के साथ अनदेखी एक अनुवाद या निष्पादन को समाप्त करे (के साथ या एक नैदानिक ​​संदेश जारी करने के बाहर हूँ-) पर्यावरण का एक दस्तावेज ढंग विशेषता में अनुवाद या प्रोग्राम निष्पादन के दौरान व्यवहार कर करने से अनुमेय अपरिभाषित व्यवहार पर्वतमाला (एक नैदानिक ​​संदेश जारी करने के साथ)।

संक्षेप में, अपरिभाषित व्यवहार का मतलब है कि आपकी प्रेमिका के गर्भवती होने पर आपकी नाक से उड़ान भरने वाले डेमन से कुछ भी हो सकता है।


अपरिभाषित व्यवहार और अनुक्रम अंक के बीच क्या संबंध है?

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

आप भी जानते ही होंगे the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified

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

int x = 5, y = 6;

int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.

एक और उदाहरण यहाँ


अब मानक §5/4कहते हैं

  • 1) पिछले और अगले अनुक्रम के बीच एक स्केलर ऑब्जेक्ट में एक अभिव्यक्ति के मूल्यांकन द्वारा एक बार में इसका संग्रहित मूल्य संशोधित होगा।

इसका क्या मतलब है?

अनौपचारिक रूप से इसका मतलब है कि दो अनुक्रम बिंदुओं के बीच एक चर को एक से अधिक बार संशोधित नहीं किया जाना चाहिए। एक अभिव्यक्ति बयान में, next sequence pointआमतौर पर समाप्त होने वाले अर्धविराम पर है, और previous sequence pointपिछले बयान के अंत में है। एक अभिव्यक्ति में मध्यवर्ती भी हो सकता है sequence points

उपरोक्त वाक्य से निम्नलिखित भाव अपरिभाषित व्यवहार को आमंत्रित करते हैं:

i++ * ++i;   // UB, i is modified more than once btw two SPs
i = ++i;     // UB, same as above
++i = 2;     // UB, same as above
i = ++i + 1; // UB, same as above
++++++i;     // UB, parsed as (++(++(++i)))

i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)

लेकिन निम्नलिखित भाव ठीक हैं:

i = (i, ++i, 1) + 1; // well defined (AFAIK)
i = (++i, i++, i);   // well defined 
int j = i;
j = (++i, i++, j*i); // well defined

  • 2) इसके अलावा, स्टोर किए जाने वाले मूल्य को निर्धारित करने के लिए पूर्व मूल्य का उपयोग किया जाएगा।

इसका क्या मतलब है? इसका अर्थ है कि यदि कोई वस्तु पूर्ण अभिव्यक्ति के भीतर लिखी गई है, तो उसी अभिव्यक्ति के भीतर किसी भी और सभी तक पहुंचने के लिए लिखा जाने वाले मूल्य की गणना में सीधे शामिल होना चाहिए

उदाहरण के लिए में i = i + 1के सभी पहुँच i(एलएचएस में और आरएचएस में) कर रहे हैं सीधे गणना में शामिल मूल्य लिखा होना चाहिए की। तो ठीक है।

यह नियम प्रभावी ढंग से उन जिसमें पहुंच प्रमाण्य संशोधन पूर्व में होना करने के लिए कानूनी भाव रोकें।

उदाहरण 1:

std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2

उदाहरण 2:

a[i] = i++ // or a[++i] = i or a[i++] = ++i etc

को अस्वीकृत कर दिया गया है क्योंकि एक्सेस करने वालों में iसे एक (में a[i]) का उस मूल्य से कोई लेना-देना नहीं है जो अंत में स्टोर किया जा रहा है, जो कि i में होता है (जो खत्म हो जाता है i++), और इसलिए इसे परिभाषित करने का कोई अच्छा तरीका नहीं है - या तो हमारी समझ के लिए या संकलक की - चाहे बढ़े हुए मूल्य को संग्रहीत करने से पहले या बाद में पहुंच होनी चाहिए। अतः व्यवहार अपरिभाषित है।

उदाहरण 3:

int x = i + i++ ;// Similar to above

C ++ 11 के उत्तर का पालन करें


45
*p++ = 4 अपरिभाषित व्यवहार नहीं है। *p++के रूप में व्याख्या की है *(p++)p++रिटर्न p(एक प्रति) और पिछले पते पर संग्रहीत मूल्य। वह यूबी क्यों लागू करेगा? यह पूरी तरह से ठीक है।
प्रसून सौरव

6
@ माइक: AFAIK, C ++ मानक की कोई (कानूनी) प्रतियाँ नहीं हैं जिनसे आप लिंक कर सकते हैं।
sbi

11
ठीक है, तो आपके पास आईएसओ के प्रासंगिक ऑर्डर पेज का लिंक हो सकता है। वैसे भी, इसके बारे में सोचते हुए, वाक्यांश "C ++ मानक का प्राथमिक ज्ञान" शब्दों के संदर्भ में थोड़ा विरोधाभास लगता है, क्योंकि यदि आप मानक पढ़ रहे हैं, तो आप प्रारंभिक स्तर से आगे हैं। हो सकता है कि हम यह बता सकें कि भाषा में आपको किन चीजों की बुनियादी समझ चाहिए, जैसे अभिव्यक्ति वाक्यविन्यास, संचालन का क्रम और शायद ऑपरेटर ओवरलोडिंग?
माइक डीसिमोन

41
मुझे यकीन नहीं है कि मानक नए उद्धरण पढ़ाने का सबसे अच्छा तरीका है
उलटा

6
@ एड्रियन पहली अभिव्यक्ति एक यूबी को आमंत्रित करता है क्योंकि अंतिम ++iऔर असाइनमेंट के बीच कोई अनुक्रम बिंदु नहीं है i। दूसरी अभिव्यक्ति यूबी को लागू नहीं करती है क्योंकि अभिव्यक्ति iका मूल्य नहीं बदलता है i। दूसरे उदाहरण में असाइनमेंट ऑपरेटर को कॉल करने से पहले i++एक अनुक्रम बिंदु ( ,) द्वारा पीछा किया जाता है।
कोलयुन

276

यह मेरे पिछले उत्तर तक अनुवर्ती है और इसमें C ++ 11 संबंधित सामग्री है।


पूर्व-आवश्यकताएं : संबंध (गणित) का एक प्राथमिक ज्ञान।


क्या यह सच है कि C ++ 11 में कोई अनुक्रम अंक नहीं हैं?

हाँ! यह एकदम सच है।

अनुक्रम अंक ने ले ली है इससे पहले कि अनुक्रम और अनुक्रम के बाद (और Unsequenced और धुंधलेपन से अनुक्रम ) संबंधों C ++ 11।


वास्तव में यह 'चीज़ से पहले का अनुक्रम' क्या है?

पहले लिया गया (.91.9 / 13) एक संबंध है जो है:

एक एकल धागे द्वारा निष्पादित मूल्यांकन के बीच और एक सख्त आंशिक क्रम 1 को प्रेरित करता है

औपचारिक रूप से इसका मतलब है कि कोई भी दो मूल्यांकन दिए गए हैं (नीचे देखें) A और B, अगर पहलेA से अनुक्रमित है B , तो निष्पादन के A पूर्व निष्पादन के लिए होगा B। तो Aइससे पहले कि अनुक्रम है नहीं Bऔर Bइससे पहले कि अनुक्रम नहीं है A, तो Aऔर Bकर रहे हैं unsequenced 2

मूल्यांकन Aऔर Bकर रहे हैं धुंधलेपन से अनुक्रम है जब या तो Aपहले अनुक्रम है Bया Bपहले अनुक्रम है A, लेकिन यह अनिर्दिष्ट जो है 3

[नोट]
1: एक सख्त आंशिक आदेश एक है द्विआधारी संबंध "<" एक सेट से अधिक Pहै जो asymmetric, और transitiveसभी के लिए, यानी, a, b, और cमें P, हम है:
........ (i)। अगर एक <b तो ¬ (b <a) ( asymmetry);
........ (ii)। अगर एक <b और b <c तो a <c ( transitivity)।
2: अनियोजित मूल्यांकन का निष्पादन ओवरलैप कर सकता है
3: अनिश्चित रूप से अनुक्रमित मूल्यांकन ओवरलैप नहीं कर सकते हैं , लेकिन या तो पहले निष्पादित किया जा सकता है।


C ++ 11 के संदर्भ में 'मूल्यांकन' शब्द का अर्थ क्या है?

C ++ 11 में, सामान्य रूप से एक अभिव्यक्ति (या एक उप-अभिव्यक्ति) का मूल्यांकन शामिल है:

  • मूल्य अभिकलन (जिसमें ग्लव्यू मूल्यांकन के लिए एक वस्तु की पहचान निर्धारित करना और पहले से मूल्यांकन के लिए एक वस्तु को सौंपा गया मूल्य प्राप्त करना शामिल है ) और

  • साइड इफेक्ट्स की दीक्षा ।

अब ((1.9 / 14) कहते हैं:

एक पूर्ण-अभिव्यक्ति के साथ जुड़े प्रत्येक मूल्य संगणना और साइड इफेक्ट का मूल्यांकन किया जाने वाले अगले पूर्ण-अभिव्यक्ति के साथ जुड़े प्रत्येक मूल्य संगणना और दुष्प्रभाव से पहले अनुक्रम किया जाता है

  • तुच्छ उदाहरण:

    int x; x = 10; ++x;

    मूल्य संगणना और साइड इफेक्ट से जुड़े मूल्य गणना और साइड इफेक्ट ++xका अनुक्रम होता हैx = 10;


तो अनिर्धारित व्यवहार और उपर्युक्त बातों के बीच कुछ संबंध होना चाहिए, है ना?

हाँ! सही।

में (mentioned1.9 / 15) यह उल्लेख किया गया है कि

जहां नोट किया गया है, सिवाय इसके कि अलग-अलग संचालकों के संचालनों का मूल्यांकन और व्यक्तिगत अभिव्यक्तियों के उप- वर्गों के मूल्यांकन के बाद 4 हैं

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

int main()
{
     int num = 19 ;
     num = (num << 3) + (num >> 3);
} 
  1. +ऑपरेटर के संचालन का मूल्यांकन एक दूसरे के सापेक्ष बिना आरोपित हैं।
  2. की ऑपरेंड का मूल्यांकन <<और >>ऑपरेटरों को एक दूसरे से unsequenced सापेक्ष हैं।

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

(Ations1.9 / 15) ऑपरेटर के परिणाम के मान की गणना संचालक के परिणाम की मूल्य गणना से पहले की जाती है।

में मतलब यह है कि x + yके मूल्य में गणना xऔर yका मूल्य गणना से पहले अनुक्रम कर रहे हैं (x + y)

अधिक महत्वपूर्ण बात

(On1.9 / 15) यदि किसी स्केलर ऑब्जेक्ट पर साइड इफेक्ट या तो संबंधित के बिना आरोपित है

(ए) एक ही स्केलर ऑब्जेक्ट पर एक और दुष्प्रभाव

या

(बी) एक ही स्केलर ऑब्जेक्ट के मूल्य का उपयोग करके एक मूल्य संगणना।

व्यवहार अपरिभाषित है

उदाहरण:

int i = 5, v[10] = { };
void  f(int,  int);
  1. i = i++ * ++i; // Undefined Behaviour
  2. i = ++i + i++; // Undefined Behaviour
  3. i = ++i + ++i; // Undefined Behaviour
  4. i = v[i++]; // Undefined Behaviour
  5. i = v[++i]: // Well-defined Behavior
  6. i = i++ + 1; // Undefined Behaviour
  7. i = ++i + 1; // Well-defined Behaviour
  8. ++++i; // Well-defined Behaviour
  9. f(i = -1, i = -1); // Undefined Behaviour (see below)

किसी फ़ंक्शन (चाहे फ़ंक्शन इनलाइन हो या नहीं) को कॉल करते समय, किसी भी तर्क अभिव्यक्ति के साथ जुड़े हर मूल्य संगणना और साइड इफेक्ट, या पोस्ट फ़ंक्शन को पोस्ट करने वाले अभिव्यक्ति के साथ, प्रत्येक अभिव्यक्ति या कथन के शरीर में निष्पादन से पहले अनुक्रमित किया जाता है। फ़ंक्शन कहा जाता है। [ नोट: मूल्य तर्क और विभिन्न तर्क अभिव्यक्तियों के साथ जुड़े साइड इफेक्ट अप्रकाशित हैं । - अंतिम नोट ]

अभिव्यक्तियाँ (5), (7)और (8)अपरिभाषित व्यवहार का आह्वान नहीं करते हैं। अधिक विस्तृत विवरण के लिए निम्नलिखित उत्तरों को देखें।


अंतिम नोट :

यदि आपको पोस्ट में कोई दोष लगता है तो कृपया एक टिप्पणी छोड़ दें। पावर-उपयोगकर्ता (rep> 20000 के साथ) कृपया टाइपोस और अन्य गलतियों को सुधारने के लिए पोस्ट को संपादित करने में संकोच न करें।


3
"असममित" के बजाय, "एंटीसिममेट्रिक" संबंधों से पहले या बाद में अनुक्रम किया जाता है। इसे बाद में दिए गए आंशिक आदेश की परिभाषा के अनुरूप पाठ में बदला जाना चाहिए (जो विकिपीडिया से भी सहमत है)।
TemplateRex

1
अंतिम उदाहरण में एक UB 7) आइटम क्यों है? शायद यह होना चाहिए f(i = -1, i = 1)?
मिखाइल

1
मैंने "संबंध से पहले अनुक्रम" का विवरण तय किया। यह एक सख्त आंशिक आदेश है । जाहिर है, एक अभिव्यक्ति को खुद से पहले अनुक्रमित नहीं किया जा सकता है, इसलिए संबंध प्रतिवर्तित नहीं हो सकता है। इसलिए यह असममित नहीं विरोधी सममित है।
थॉमसमैकलॉड

1
5) अच्छी तरह से किया जा रहा है मेरे दिमाग से उड़ा दिया। जोहानस शाउब द्वारा की गई व्याख्या पूरी तरह से सरल नहीं थी। विशेष रूप से इसलिए कि मैं मानता था कि ++i( +इसका उपयोग करने वाले ऑपरेटर से पहले मूल्यांकन किया जा रहा है) में भी, मानक अभी भी यह नहीं कहता है कि इसका दुष्प्रभाव समाप्त होना चाहिए। लेकिन वास्तव में, क्योंकि यह एक रेफरी है lvalueजो iखुद ही है, यह जरूरी है कि साइड इफेक्ट खत्म हो गया है क्योंकि मूल्यांकन समाप्त होना चाहिए, इसलिए मूल्य को अद्यतित होना चाहिए। यह वास्तव में पाने के लिए पागल हिस्सा था।
v.oddou

"आईएसओ सी ++ समिति के सदस्यों ने सोचा कि अनुक्रम अंक सामान को समझना काफी मुश्किल था। इसलिए उन्होंने इसे केवल स्पष्ट शब्दों और अधिक स्पष्टता के लिए उपर्युक्त संबंधों के साथ बदलने का फैसला किया।" - क्या आपको उस दावे का संदर्भ मिला है? यह मुझे लगता है कि नए संबंधों को समझना कठिन है।
एमएम

30

C ++ 17 ( N4659) में Idiomatic C ++ के लिए रिफाइनिंग एक्सप्रेशन अभिव्यक्ति मूल्यांकन आदेश शामिल है जो अभिव्यक्ति मूल्यांकन के एक सख्त आदेश को परिभाषित करता है।

विशेष रूप से, में निम्नलिखित वाक्य

8.18 असाइनमेंट और कंपाउंड असाइनमेंट ऑपरेटर :
...।

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

निम्नलिखित स्पष्टीकरण के साथ

एक एक्सप्रेशन एक्स को एक्सप्रेशन वाई से पहले अनुक्रमित करने के लिए कहा जाता है यदि एक्सप्रेशन एक्स से जुड़ी हर वैल्यू कंप्यूटेशन और हर साइड इम्पैक्ट को हर वैल्यू कंप्यूटेशन और एक्सप्रेशन वाई से जुड़े हर साइड इफेक्ट से पहले सीक्वेंस किया जाता है ।

पहले से अपरिभाषित व्यवहार के कई मामलों को वैध बनाएं, जिसमें एक प्रश्न शामिल है:

a[++i] = i;

हालांकि कई अन्य इसी तरह के मामले अभी भी अपरिभाषित व्यवहार की ओर ले जाते हैं।

इन N4140:

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

लेकीन मे N4659

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

बेशक, सी ++ 17 आज्ञाकारी संकलक का उपयोग करने का मतलब यह नहीं है कि किसी को इस तरह के भाव लिखना शुरू करना चाहिए।


i = i++ + 1;c ++ 17 में परिभाषित व्यवहार क्यों है, मुझे लगता है कि भले ही "दाहिने ऑपरेंड को बाएं ऑपरेंड से पहले अनुक्रमित किया जाता है", हालांकि "i ++" के लिए संशोधन और असाइनमेंट के लिए साइड इफेक्ट अप्रकाशित हैं, कृपया इनकी व्याख्या करने के लिए अधिक विवरण दें
जैक X

@jackX मैंने उत्तर बढ़ाया :)।
एलेक्सड

हाँ, मुझे लगता है कि वाक्य की व्याख्या का विस्तार "दायाँ संचालक बाएं संकार्य से पहले अनुक्रमित है" अधिक उपयोगी है। क्योंकि "दाहिने संकार्य को बाएँ संकार्य से पहले अनुक्रमित किया जाता है" का अर्थ है मान संकेंद्रण से जुड़े मान गणना और दुष्प्रभाव इससे पहले कि बाएं ऑपरेंड का अनुक्रम हो। जैसा कि आपने :-)
जैक एक्स

11

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

f (a,b)

पहले या तो एक बी, या, बी फिर ए। अब, ए और बी को अलग-अलग कोर पर या तो निर्देश के साथ मूल्यांकन किया जा सकता है।


5
मेरा मानना ​​है कि हालाँकि, अगर 'a' या 'b' में फंक्शन कॉल शामिल है, तो वे बिना शर्त के बजाय अनिश्चित रूप से अनुक्रमित होते हैं, जो यह कहता है कि किसी भी तरह के साइड-इफेक्ट से पहले सभी साइड-इफेक्ट्स होने की आवश्यकता होती है अन्य, हालांकि संकलक के अनुरूप होने की आवश्यकता नहीं है जिसके बारे में पहले जाना जाता है। यदि यह अब सत्य नहीं है, तो यह बहुत सारे कोड को तोड़ देगा जो कि ओवरलैपिंग नहीं होने वाले ऑपरेशनों पर निर्भर करता है (उदाहरण के लिए यदि 'a' और 'b' प्रत्येक सेट अप, उपयोग, और नीचे ले जाएँ, एक साझा स्टेटिक स्टेट)।
सुपरकैट

2

में C99(ISO/IEC 9899:TC3)जो इस चर्चा अब तक निम्नलिखित steteents evaluaiton के आदेश के बारे में किया जाता है से अनुपस्थित है।

[...] सबएक्सप्रेस के मूल्यांकन का क्रम और जिस क्रम में साइड इफेक्ट होते हैं, दोनों अनिर्दिष्ट हैं। (धारा 6.5 पीपी 67)

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


2
प्रश्न को C ++ और C को टैग नहीं किया गया है, जो अच्छा है क्योंकि C ++ 17 में व्यवहार पुराने संस्करणों में व्यवहार से काफी अलग है - और C11, C99, C90, आदि के व्यवहार से कोई संबंध नहीं रखता है या भालू बहुत कम है। इसके संबंध में। कुल मिलाकर, मैं इसे हटाने का सुझाव दूंगा। अधिक महत्वपूर्ण रूप से, हमें C के लिए बराबर Q & A को खोजने और यह सुनिश्चित करने की आवश्यकता है कि यह ठीक है (और ध्यान दें कि C ++ 17, विशेष रूप से, नियमों में बदलाव करता है - C ++ 11 में व्यवहार और उससे पहले का व्यवहार कमोबेश यही था C11 में, हालाँकि C में इसका वर्णन करने वाली क्रिया अभी भी 'अनुक्रम बिंदु' का उपयोग करती है जबकि C ++ 11 और बाद में नहीं।
जोनाथन लेफ़लर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.