अनुक्रम बिंदु
C (प्रोग्रामिंग लैंग्वेज) और C++ में, एक अनुक्रम बिंदु कंप्यूटर प्रोग्राम के निष्पादन (कंप्यूटिंग) में किसी भी बिंदु को परिभाषित करता है, जिस पर यह आश्वासन दी जाती है कि पिछले मूल्यांकन के सभी दुष्प्रभाव (कंप्यूटर विज्ञान) किए गए हैं, और कोई साइड इफेक्ट नहीं है बाद के मूल्यांकन अभी तक किए गए हैं। वे वैधता का निर्धारण करने के लिए एक मूल अवधारणा हैं, और यदि मान्य हैं, तो अभिव्यक्ति के संभावित परिणाम अधिक अनुक्रम बिंदु जोड़ना कभी-कभी अभिव्यक्ति को परिभाषित करने और मूल्यांकन के एकल वैध क्रम को सुनिश्चित करने के लिए आवश्यक होता है।
C11 और C++11 के साथ, अनुक्रम बिंदु शब्द के उपयोग को अनुक्रमण द्वारा प्रतिस्थापित कर दिया गया है। तीन संभावनाएँ हैं::[1][2][3]
- एक अभिव्यक्ति का मूल्यांकन किसी अन्य अभिव्यक्ति से पहले अनुक्रमित किया जा सकता है, या समकक्ष अन्य अभिव्यक्ति का मूल्यांकन पहले के बाद अनुक्रमित किया जाता है।
- अभिव्यक्तियों का मूल्यांकन अनिश्चित रूप से अनुक्रमित है, जिसका अर्थ है कि एक दूसरे से पहले अनुक्रमित है, किंतु जो अनिर्दिष्ट है।
- अभिव्यक्तियों का मूल्यांकन अनुक्रमित है।
अअनुक्रमित मूल्यांकनों का निष्पादन ओवरलैप हो सकता है, जिससे यदि वे स्थिति साझा करते हैं तो संभावित रूप से विनाशकारी अपरिभाषित व्यवहार हो सकता है। यह स्थिति समानांतर गणनाओं में उत्पन्न हो सकती है, जिससे दौड़ की स्थिति उत्पन्न हो सकती है, किंतु अपरिभाषित व्यवहार के परिणामस्वरूप एकल-थ्रेडेड स्थिति भी हो सकती है। उउदाहरण के लिए, a[i] = i++;
(कहाँ a
एक सरणी है और i
एक पूर्णांक है) में अपरिभाषित व्यवहार है।
अस्पष्टता के उदाहरण
दो फ़ंक्शनf()
और g()
. पर विचार करें C और C++ में, + ऑपरेटर अनुक्रम बिंदु से संबद्ध नहीं है, और इसलिए अभिव्यक्तिf()+g()
में यह संभव है कि या तो f()
या g()
पहले निष्पादित किया जाएगा। अल्पविराम ऑपरेटर एक अनुक्रम बिंदु प्रस्तुत करता है, और इसलिए कोड f(),g()
में मूल्यांकन का क्रम परिभाषित किया गया है: पहले f()
कहा जाता है, और फिरg()
कहा जाता है।
अनुक्रम बिंदु तब भी चलन में आते हैं जब एक ही अभिव्यक्ति के अंदर एक ही चर को एक से अधिक बार संशोधित किया जाता है। अधिकांशतः उद्धृत किया जाने वाला उदाहरण C एक्सप्रेशन i=i++
,है, जो वास्तविक रूप में i
को उसका पिछला मान निर्दिष्ट करता है और i
में वृद्धि करता है। i
का अंतिम मान अस्पष्ट है, क्योंकि, अभिव्यक्ति मूल्यांकन के क्रम के आधार पर, वेतन वृद्धि असाइनमेंट से पहले, बाद में या इंटरलीव्ड हो सकती है। किसी विशेष भाषा की परिभाषा संभावित व्यवहारों में से एक को निर्दिष्ट कर सकती है या यूं कहें कि व्यवहार अपरिभाषित है। C और C++ में, ऐसी अभिव्यक्ति का मूल्यांकन करने से अपरिभाषित व्यवहार प्राप्त होता है।[4] अन्य भाषाएँ, जैसे C#, असाइनमेंट और इंक्रीमेंट ऑपरेटर की प्राथमिकता को इस तरह से परिभाषित करती हैं कि अभिव्यक्ति i=i++
के परिणाम की प्रत्याभूति होती है।
व्यवहार
C++ 03 तक
C और C++[5] [6] में अनुक्रम बिंदु निम्न स्थानों पर होते हैं। (C++ में, ऑपरेटर ओवरलोडिंग कार्य कार्यों की तरह कार्य करता है, और इस प्रकार ऑपरेटरों को ओवरलोड किया गया है जो फ़ंक्शन कॉल के समान ही अनुक्रम बिंदु प्रस्तुत करते हैं।)
- && (तार्किक AND), || के बाएँ और दाएँ ऑपरेंड के मूल्यांकन के बीच (तार्किक OR) (लघु-परिपथ मूल्यांकन के भाग के रूप में), और अल्पविराम ऑपरेटर। उदाहरण के लिए, अभिव्यक्ति
*p++ != 0 && *q++ != 0
में, उप-अभिव्यक्ति*p++ != 0
के सभी दुष्प्रभाव q तक पहुंचने के किसी भी प्रयास से पहले पूरे हो जाते हैं। - टर्नरी कंडीशनल ऑपरेटर के पहले ऑपरेंड और उसके दूसरे या तीसरे ऑपरेंड के मूल्यांकन के बीच उदाहरण के लिए, अभिव्यक्ति में
a = (*p++) ? (*p++) : 0
पहले*p++
के बाद एक अनुक्रम बिंदु है, जिसका अर्थ है कि दूसरे उदाहरण के निष्पादित होने तक यह पहले ही बढ़ चुका है। - पूर्ण अभिव्यक्ति के अंत में. इस श्रेणी में अभिव्यक्ति कथन (जैसे असाइनमेंट
a=b;
;), रिटर्न कथन,if
,switch
,while
, याdo
-while
कथनों के नियंत्रक भाव औरfor
कथन में तीन भावों में से प्रत्येक सम्मिलित हैं। - किसी फ़ंक्शन को फ़ंक्शन कॉल में अंकित करने से पहले। जिस क्रम में तर्कों का मूल्यांकन किया जाता है वह निर्दिष्ट नहीं है, किंतु इस अनुक्रम बिंदु का अर्थ है कि फ़ंक्शन अंकित करने से पहले उनके सभी दुष्प्रभाव पूरे हो गए हैं। अभिव्यक्ति
f(i++) + g(j++) + h(k++)
में,f
कोi
के मूल मान के एक पैरामीटर के साथ बुलाया जाता है, किंतुi
कोf
के मुख्य भाग में प्रवेश करने से पहले i को बढ़ाया जाता है। इसी प्रकार,j
औरk
को क्रमशःg
औरh
अंकित करने से पहले अद्यतन किया जाता है। चूँकि यह निर्दिष्ट नहीं है कि किस क्रम मेंf()
,g()
,h()
निष्पादित किए गए हैं, न ही किस क्रम मेंi
,j
,k
को बढ़ाया गया है। यदिf
का निकाय वेरिएबलj
औरk
तक पहुंचता है, तो यह दोनों, न तो, या उनमें से केवल एक को बढ़ा हुआ पा सकता है। (फ़ंक्शन कॉलf(a,b,c)
अल्पविराम ऑपरेटर का उपयोग नहीं है;a
,b
औरc
के लिए मूल्यांकन का क्रम अनिर्दिष्ट है।) - फ़ंक्शन रिटर्न पर, रिटर्न वैल्यू को कॉलिंग संदर्भ में कॉपी करने के बाद। (यह अनुक्रम बिंदु केवल C++ मानक में निर्दिष्ट है; यह केवल सी में निहित रूप से उपस्थित है।[7])
- प्रारंभकर्ता के अंत में; उदाहरण के लिए, घोषणा में
5
के मूल्यांकन के बादint a = 5;
;। - प्रत्येक घोषणाकर्ता अनुक्रम में प्रत्येक घोषणाकर्ता के बीच; उदाहरण के लिए, के दो मूल्यांकनों के बीच
a++
मेंint x = a++, y = a++
.[8] (यह कॉमा ऑपरेटर का उदाहरण नहीं है।) - प्रत्येक रूपांतरण के बाद एक इनपुट/आउटपुट प्रारूप विनिर्देशक के साथ जुड़ा हुआ है। उदाहरण के लिए, अभिव्यक्ति
printf("foo %n %d", &a, 42)
) में,%n
के मूल्यांकन के बाद और42
को प्रिंट करने से पहले एक अनुक्रम बिंदु होता है।
C11 और C++11
आंशिक रूप से थ्रेड्स के लिए भाषा समर्थन की शुरुआत के कारण, C11 और C++11 ने मूल्यांकन क्रम के लिए नई शब्दावली प्रस्तुत की। एक ऑपरेशन को दूसरे से पहले अनुक्रमित किया जा सकता है, या दोनों को अनिश्चित रूप से अनुक्रमित किया जा सकता है (एक को दूसरे से पहले पूरा करना होगा) या बिना अनुक्रमित (प्रत्येक अभिव्यक्ति में संचालन को इंटरलीव किया जा सकता है)।
सी ++ 17
C++17 ने मूल्यांकन आदेश के कई पहलुओं को प्रतिबंधित किया। new}ew
अभिव्यक्ति हमेशा निर्माता तर्कों का मूल्यांकन करने से पहले स्मृति आवंटन करेगी। संचालक <<
, >>
, .
, .*
, ->*
, और सबस्क्रिप्ट और फ़ंक्शन कॉल ऑपरेटर को बाएं से दाएं मूल्यांकन करने की आश्वासन है (चाहे वे अतिभारित हों या नहीं)। उदाहरण के लिए, कोड
std::cout << a() << b() << c(); // parsed as (((std::cout << a()) << b()) << c());
उस क्रम मेंa
, b
और c
को कॉल करने की नई आश्वासन दी गई है। असाइनमेंट-जैसे ऑपरेटर के बाईं ओर का मूल्यांकन दाईं ओर से पहले किया जाता है, जिससे a() *= b();
मूल्यांकन करने का आश्वासन दिया है a
पहला अंत में, चूँकि जिस क्रम में फ़ंक्शन पैरामीटर का मूल्यांकन किया जाता है वह कार्यान्वयन-परिभाषित रहता है, संकलक को अब कई पैरामीटर में उप-अभिव्यक्तियों को इंटरलीव करने की अनुमति नहीं है।[9]
संदर्भ
- ↑ "ISO/IEC 14882:2011". Retrieved 2012-07-04.
- ↑ "A finer-grained alternative to sequence points (revised) (WG21/N2239 J16/07-0099)". Retrieved 2012-07-05.
- ↑ "मूल्यांकन का क्रम". Retrieved 2015-10-14.
- ↑ Clause 6.5#2 of the C99 specification: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored."
- ↑ Annex C of the C99 specification lists the circumstances under which a sequence point may be assumed.
- ↑ The 1998 C++ standard lists sequence points for that language in section 1.9, paragraphs 16–18.
- ↑ C++ standard, ISO 14882:2003, section 1.9, footnote 11.
- ↑ C++ standard, ISO 14882:2003, section 8.3: "Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself."
- ↑ Dos Reis, Gabriel; Sutter, Herb; Caves, Jonathan (2016-06-23). "मुहावरेदार सी ++ के लिए रिफाइनिंग एक्सप्रेशन इवैल्यूएशन ऑर्डर" (PDF). open-std.org. pp. 1–5. Retrieved 28 April 2023.
बाहरी संबंध
- Question 3.8 of the FAQ for comp.lang.c