c++ - रचन - अल्पविराम के साथ टर्नरी ऑपरेटर सच्चे मामले में केवल एक अभिव्यक्ति का मूल्यांकन क्यों करता है?



विराम चिन्ह के प्रकार 16 (4)

C ++ कंपाइलर कोड क्यों उत्पन्न करेगा जो कि टर्नरी ऑपरेटर की सच्ची शाखा के लिए केवल वेतन वृद्धि x

आपने गलत समझा है कि क्या हुआ है। x और y दोनों की सच्ची-शाखा वेतन वृद्धि। हालांकि, इसके तुरंत बाद, y बिना शर्त के डिक्रिप्टेड है।

यहाँ यह है कि ऐसा कैसे होता है: चूंकि C + ++ में सशर्त ऑपरेटर कॉमा ऑपरेटर की तुलना में अधिक पूर्वता रखते हैं , इसलिए संकलक अभिव्यक्ति को इस प्रकार बताता है:

   (someValue ? ++x, ++y : --x), (--y);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^

अल्पविराम के बाद "अनाथ" पर ध्यान दें। यह वही है जो शुरू में वृद्धि हुई है कि y को घटाना है।

मैं भी इस तरह से सच्ची शाखा के चारों ओर कोष्ठक डालने के रूप में दूर चला गया:

someValue ? (++x, ++y) : --x, --y;

आप सही रास्ते पर थे, लेकिन आपने एक गलत शाखा को छोटा कर दिया: आप इसे अन्य शाखा की तरह ही कोष्ठक द्वारा ठीक कर सकते हैं:

someValue ? ++x, ++y : (--x, --y);

डेमो (प्रिंट 11 11)

https://src-bin.com

मैं वर्तमान में C ++ प्राइमर पुस्तक के साथ C ++ सीख रहा हूं और पुस्तक में एक अभ्यास है:

बताएं कि निम्नलिखित अभिव्यक्ति क्या करती है: someValue ? ++x, ++y : --x, --y someValue ? ++x, ++y : --x, --y

हम क्या जानते हैं? हम जानते हैं कि टर्नरी ऑपरेटर का कॉमा ऑपरेटर की तुलना में अधिक पूर्वता है। बाइनरी ऑपरेटरों के साथ यह समझना काफी आसान था, लेकिन टर्नरी ऑपरेटर के साथ मैं थोड़ा संघर्ष कर रहा हूं। द्विआधारी ऑपरेटरों के साथ "उच्च प्राथमिकता" होने का मतलब है कि हम अभिव्यक्ति के चारों ओर कोष्ठक का उपयोग उच्च वरीयता के साथ कर सकते हैं और यह निष्पादन को नहीं बदलेगा।

टर्नरी ऑपरेटर के लिए मैं यह करूंगा:

(someValue ? ++x, ++y : --x, --y)

प्रभावी रूप से उसी कोड के परिणामस्वरूप जो मुझे समझने में मदद नहीं करता है कि कंपाइलर कोड को कैसे समूहीकृत करेगा।

हालाँकि, C ++ कंपाइलर के साथ परीक्षण करने से मुझे पता है कि अभिव्यक्ति संकलित है और मुझे नहीं पता है कि : a : ऑपरेटर खुद के लिए खड़ा हो सकता है। तो संकलक को टर्नेरी ऑपरेटर की सही व्याख्या करना प्रतीत होता है।

फिर मैंने कार्यक्रम को दो तरीकों से अंजाम दिया:

#include <iostream>

int main()
{
    bool someValue = true;
    int x = 10, y = 10;

    someValue ? ++x, ++y : --x, --y;

    std::cout << x << " " << y << std::endl;
    return 0;
}

का परिणाम:

11 10

जबकि दूसरी ओर someValue = false यह प्रिंट करता है:

9 9

C ++ कंपाइलर कोड क्यों उत्पन्न करेगा जो कि टर्नेरी ऑपरेटर की सच्ची शाखा के लिए केवल वेतन वृद्धि x , जबकि टर्नरी की झूठी शाखा के लिए यह x और y दोनों को घटाता है?

मैं भी इस तरह से सच्ची शाखा के चारों ओर कोष्ठक डालने के रूप में दूर चला गया:

someValue ? (++x, ++y) : --x, --y;

लेकिन यह अभी भी 11 10 में परिणाम है।


Answer #1

आपकी समस्या यह है कि तिर्यक अभिव्यक्ति का वास्तव में अल्पविराम से अधिक पूर्वता नहीं है। वास्तव में, C ++ को केवल पूर्वता के अनुसार सटीक रूप से वर्णित नहीं किया जा सकता है - और यह त्रैमासिक ऑपरेटर और अल्पविराम के बीच की बातचीत है जहां यह टूट जाता है।

a ? b++, c++ : d++

के रूप में इलाज किया जाता है:

a ? (b++, c++) : d++

(अल्पविराम ऐसा व्यवहार करता है जैसे कि इसकी उच्चता है)। दूसरी ओर,

a ? b++ : c++, d++

के रूप में इलाज किया जाता है:

(a ? b++ : c++), d++

और टर्नरी ऑपरेटर उच्च पूर्वता है।


Answer #2

जैसा कि @Rakete ने अपने उत्कृष्ट उत्तर में कहा, यह मुश्किल है। मैं उस पर थोड़ा जोड़ना चाहूंगा।

टर्नरी ऑपरेटर के पास फॉर्म होना चाहिए:

तार्किक-या-अभिव्यक्ति ? अभिव्यक्ति : असाइनमेंट-एक्सप्रेशन

तो हमारे पास निम्न मैपिंग हैं:

  • someValue : तार्किक-या-अभिव्यक्ति
  • ++x, ++y : अभिव्यक्ति
  • ??? असाइनमेंट-एक्सप्रेशन --x, --y या केवल --x ?

वास्तव में यह केवल --x क्योंकि एक असाइनमेंट एक्सप्रेशन को कॉमा द्वारा अलग किए गए दो एक्सप्रेशन के रूप में पार्स नहीं किया जा सकता है (C ++ के व्याकरण नियमों के अनुसार), इसलिए --x, --y को असाइनमेंट एक्सप्रेशन के रूप में नहीं माना जा सकता है।

इस तरह से देखने के लिए टर्नरी (सशर्त) अभिव्यक्ति भाग का परिणाम होता है:

someValue?++x,++y:--x

यह पठनीयता के लिए ++x,++y की गणना करने में मदद कर सकता है, जैसे कि यदि कोष्ठक (++x,++y) ; कुछ भी शामिल है ? और : सशर्त के बाद अनुक्रमित किया जाएगा। (मैं उन्हें बाकी पोस्ट के लिए संक्षिप्त करूँगा)।

और इस क्रम में मूल्यांकन किया गया:

  1. someValue?
  2. (++x,++y) या --x (1. के bool परिणाम पर निर्भर करता है)

इस अभिव्यक्ति को तब अल्पविराम ऑपरेटर के रूप में बाएं उप-अभिव्यक्ति के रूप में माना जाता है, जिसमें सही उप-अभिव्यक्ति होती है - जैसे,

(someValue?(++x,++y):--x), --y;

जिसका अर्थ है कि बाईं ओर एक त्याग-मूल्य अभिव्यक्ति है , जिसका अर्थ है कि इसका मूल्यांकन निश्चित रूप से किया गया है, लेकिन फिर हम दाईं ओर का मूल्यांकन करते हैं और उसे वापस करते हैं।

तो क्या होता है जब someValue true होता true ?

  1. (someValue?(++x,++y):--x) x और y को 11 से 11 तक बढ़ाता और बढ़ाता है।
  2. बाईं अभिव्यक्ति को छोड़ दिया गया है (हालांकि वेतन वृद्धि के दुष्प्रभाव बने हुए हैं)
  3. हम कॉमा ऑपरेटर के दाहिने हाथ की ओर का मूल्यांकन करते हैं: --y , जो फिर y को 10 --y

व्यवहार को "ठीक" करने के लिए, आप --x, --y को कोष्ठक के साथ एक प्राथमिक अभिव्यक्ति में बदल सकते हैं जो कि असाइनमेंट-अभिव्यक्ति के लिए एक मान्य प्रविष्टि है: *

someValue?++x,++y:(--x, --y);

* यह एक बल्कि अजीब लंबी श्रृंखला है जो एक असाइनमेंट-एक्सप्रेशन को एक प्राथमिक अभिव्यक्ति से जोड़ता है:

असाइनमेंट-एक्सप्रेशन --- (शामिल हो सकता है) -> सशर्त-अभिव्यक्ति -> तार्किक-या-अभिव्यक्ति -> तार्किक-और-अभिव्यक्ति -> समावेशी-या-अभिव्यक्ति -> अनन्य-या-अभिव्यक्ति - -> और अभिव्यक्ति -> समानता-अभिव्यक्ति -> संबंधपरक अभिव्यक्ति -> बदलाव-अभिव्यक्ति -> योजक-अभिव्यक्ति -> गुणन-अभिव्यक्ति -> दोपहर-अभिव्यक्ति -> कास्ट-अभिव्यक्ति -> एकात्मक-अभिव्यक्ति -> उपसर्ग-अभिव्यक्ति -> प्राथमिक-अभिव्यक्ति


Answer #3

वाह, यह मुश्किल है।

संकलक आपकी अभिव्यक्ति को इस रूप में देखता है:

(someValue ? (++x, ++y) : --x), --y;

टर्नरी ऑपरेटर को इसकी आवश्यकता है : यह उस संदर्भ में स्वयं नहीं खड़ा हो सकता है, लेकिन इसके बाद, कोई कारण नहीं है कि अल्पविराम झूठे मामले से संबंधित होना चाहिए।

अब यह अधिक समझ में आता है कि आपको वह आउटपुट क्यों मिलता है। यदि someValue सही है, तो ++x , ++y और --y निष्पादित हो जाते हैं, जो प्रभावी रूप से y नहीं बदलता है, लेकिन एक से x जोड़ता है।

यदि someValue गलत है, तो --x और --y निष्पादित होते हैं, दोनों को एक-एक करके --y हैं।





conditional-operator