कोमा संचालक कैसे काम करता है


175

कॉमा ऑपरेटर सी ++ में कैसे काम करता है?

उदाहरण के लिए, अगर मैं करता हूं:

a = b, c;  

क्या एक अंत बी या सी को बराबर करता है?

(हां, मुझे पता है कि यह परीक्षण करना आसान है - किसी को जल्दी से जवाब खोजने के लिए यहां पर दस्तावेजीकरण करना।)

अद्यतन: इस सवाल ने अल्पविराम ऑपरेटर का उपयोग करते समय एक बारीकियों को उजागर किया है। बस इस दस्तावेज़ के लिए:

a = b, c;    // a is set to the value of b!

a = (b, c);  // a is set to the value of c!

यह प्रश्न वास्तव में कोड में एक टाइपो से प्रेरित था। क्या होने का इरादा था?

a = b;
c = d;

में बदल गया

a = b,    //  <-  Note comma typo!
c = d;

इस बारे में यहां और पढ़ें। stackoverflow.com/questions/12824378/…
कोडिंग मैश

1
के संभावित डुप्लिकेट अल्पविराम ऑपरेटर `, क्या करता है` सी में करते हैं? । यह आपको एक दिन हरा देता है। और लिल्क का उत्तर प्रश्न के बारे में एक उत्तर प्रदान करता है a = (b, c);
jww

5
लेकिन इस मामले में a = b, c = d;वास्तव में इरादा के रूप में ही प्रदर्शन करता है a = b; c = d;?
बॉन्डोलिन

@NargothBond जरूरी नहीं है। तो bऔर dसमारोह के मूल्यांकन कि उपयोग (और संशोधित) एक आम राज्य कर रहे हैं, निष्पादन आदेश तक परिभाषित नहीं है C++17
नीरोनियम

जवाबों:



129

ध्यान रखें कि कॉमा ऑपरेटर को C ++ में ओवरलोड किया जा सकता है। इस प्रकार वास्तविक व्यवहार अपेक्षा से बहुत भिन्न हो सकता है।

एक उदाहरण के रूप में, Boost.Spirit प्रतीक तालिकाओं के लिए सूची आरंभीक को लागू करने के लिए बहुत चतुराई से अल्पविराम ऑपरेटर का उपयोग करता है। इस प्रकार, यह निम्नलिखित वाक्यविन्यास को संभव और सार्थक बनाता है:

keywords = "and", "or", "not", "xor";

ध्यान दें कि ऑपरेटर पूर्वता के कारण, कोड (जानबूझकर!) के समान है

(((keywords = "and"), "or"), "not"), "xor";

अर्थात्, पहला ऑपरेटर जिसे keywords.operator =("and")एक प्रॉक्सी ऑब्जेक्ट लौटाता है, जिस पर शेष operator,एस लागू होते हैं:

keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");

उम्म, आप पूर्वता को नहीं बदल सकते, हालांकि, आपको अपनी सूची में संभवतः कोष्ठक लगाना चाहिए।
जेफ बर्गेज

18
@ जेफ इसके विपरीत। सूची के चारों ओर एक कोष्ठक के साथ यह तब से काम नहीं करेगा क्योंकि कंपाइलर केवल दो के बीच अल्पविराम ऑपरेटर को देखता है char[], जिसे अतिभारित नहीं किया जा सकता है। कोड जानबूझकर पहले कॉल करता है operator=और फिर बाद operator,में प्रत्येक शेष तत्व के लिए।
कोनराड रुडोल्फ

125

अल्पविराम ऑपरेटर में सभी C / C ++ ऑपरेटरों की सबसे कम पूर्वता है। इसलिए यह हमेशा एक अभिव्यक्ति को बांधने वाला आखिरी होता है, जिसका अर्थ है:

a = b, c;

के बराबर है:

(a = b), c;

एक और दिलचस्प तथ्य यह है कि अल्पविराम ऑपरेटर एक अनुक्रम बिंदु का परिचय देता है । इसका मतलब है कि अभिव्यक्ति:

a+b, c(), d

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

someFunc(arg1, arg2, arg3)

तर्कों का मूल्यांकन मनमाने ढंग से किया जा सकता है। ध्यान दें कि फ़ंक्शन कॉल में अल्पविराम ऑपरेटर नहीं हैं ; वे विभाजक हैं।


15
वर्थ उनका कहना है कि ,है इतनी कम पूर्वता, तो यह और भी पीछे है ही ;) ... यही कारण है: अल्पविराम-जैसे- ऑपरेटर कॉमा-जैसे- की तुलना में कम पूर्वता है विभाजक । इसलिए, यदि आप किसी एकल फ़ंक्शन तर्क, चर असाइनमेंट, या अन्य अल्पविराम से अलग सूची के भीतर अल्पविराम- ऑपरेटर का उपयोग करना चाहते हैं - तो आपको कोष्ठक का उपयोग करने की आवश्यकता है, जैसे:int a = 1, b = 2, weirdVariable = (++a, b), d = 4;
underscore_d

68

अल्पविराम ऑपरेटर:

  • सबसे कम पूर्वता है
  • बाईं सहयोगी है

अल्पविराम ऑपरेटर का एक डिफ़ॉल्ट संस्करण सभी प्रकार (अंतर्निहित और कस्टम) के लिए परिभाषित किया गया है, और यह निम्नानुसार काम करता है - दिया गया है exprA , exprB:

  • exprA मूल्यांकन किया है
  • के परिणाम exprAको नजरअंदाज कर दिया जाता है
  • exprB मूल्यांकन किया है
  • का परिणाम exprBपूरे अभिव्यक्ति के परिणाम के रूप में लौटा है

अधिकांश ऑपरेटरों के साथ, संकलक को निष्पादन के आदेश का चयन करने की अनुमति दी जाती है और यदि अंतिम परिणाम को प्रभावित नहीं करता है (जैसे false && foo()कॉल को छोड़ देगा foo) तो निष्पादन को छोड़ना आवश्यक है । यह हालांकि अल्पविराम ऑपरेटर के लिए मामला नहीं है और उपरोक्त चरण हमेशा * होगा ।

व्यवहार में, डिफ़ॉल्ट अल्पविराम ऑपरेटर अर्धविराम के समान ही काम करता है। अंतर यह है कि अर्धविराम द्वारा अलग किए गए दो भाव दो अलग-अलग कथन बनाते हैं, जबकि अल्पविराम-अलगाव सभी को एक ही अभिव्यक्ति के रूप में रखता है। यही कारण है कि अल्पविराम ऑपरेटर को कभी-कभी निम्नलिखित परिदृश्य में उपयोग किया जाता है:

  • C वाक्यविन्यास के लिए एक अभिव्यक्ति की आवश्यकता होती है , न कि कथन की। जैसे मेंif( HERE )
  • C वाक्यविन्यास के लिए एक कथन की आवश्यकता होती है, अधिक नहीं, उदाहरण के लिए forलूप के प्रारंभ मेंfor ( HERE ; ; )
  • जब आप घुंघराले ब्रेसिज़ को छोड़ना चाहते हैं और एक ही बयान रखना चाहते हैं: if (foo) HERE ;(कृपया ऐसा न करें, यह वास्तव में बदसूरत है!)

जब एक कथन एक अभिव्यक्ति नहीं है, अर्धविराम को अल्पविराम द्वारा प्रतिस्थापित नहीं किया जा सकता है। उदाहरण के लिए ये अस्वीकृत हैं:

  • (foo, if (foo) bar)( ifअभिव्यक्ति नहीं है)
  • int x, int y (चर घोषणा कोई अभिव्यक्ति नहीं है)

आपके मामले में हमारे पास है:

  • a=b, c;, के बराबर a=b; c;, यह मानते हुए कि उस aप्रकार का है जो अल्पविराम ऑपरेटर को अधिभार नहीं देता है।
  • a = b, c = d;समतुल्य a=b; c=d;, यह मानते हुए कि उस aप्रकार का है जो अल्पविराम ऑपरेटर को अधिभारित नहीं करता है।

ध्यान दें कि हर अल्पविराम वास्तव में एक अल्पविराम ऑपरेटर नहीं है। कुछ अल्पविराम जिनका एक बिल्कुल अलग अर्थ है:

  • int a, b; --- चर घोषणा सूची अल्पविराम से अलग है, लेकिन ये अल्पविराम संचालक नहीं हैं
  • int a=5, b=3; --- यह एक अल्पविराम से अलग परिवर्तनीय घोषणा सूची भी है
  • foo(x,y)--- अल्पविराम से अलग तर्क सूची। वास्तव में, xऔर किसी भी क्रम yमें मूल्यांकन किया जा सकता है !
  • FOO(x,y) --- अल्पविराम-पृथक मैक्रो तर्क सूची
  • foo<a,b> --- अल्पविराम से अलग टेम्पलेट तर्क सूची
  • int foo(int a, int b) --- अल्पविराम से अलग पैरामीटर सूची
  • Foo::Foo() : a(5), b(3) {} --- एक क्लास कंस्ट्रक्टर में अल्पविराम द्वारा अलग की गई इनिशियलाइज़र सूची

* यदि आप अनुकूलन लागू करते हैं तो यह पूरी तरह सच नहीं है। यदि संकलक पहचानता है कि कोड के कुछ टुकड़े का बाकी पर बिल्कुल कोई प्रभाव नहीं है, तो यह अनावश्यक बयानों को हटा देगा।

आगे पढ़े: http://en.wikipedia.org/wiki/Comma_operator


क्या यह ध्यान देने योग्य है कि यदि operator ,अतिभारित है तो आप सहानुभूति पर कोई गारंटी खो देते हैं (जैसे आप शॉर्ट-सर्किट गुणों को खो देते हैं operator&&और operator||यदि वे अतिभारित होते हैं)?
यंगजॉन

ओवरलोड होने या न होने के बावजूद कोमा-ऑपरेटर वाम-साहचर्य है। एक अभिव्यक्ति a, b, cहमेशा मतलब है (a, b), cऔर कभी नहीं a, (b, c)। उत्तरार्द्ध व्याख्या भी त्रुटि संकलन के लिए नेतृत्व कर सकती है यदि तत्व विभिन्न प्रकार के हैं। तर्क के मूल्यांकन के क्रम के बाद आप क्या हो सकते हैं? मुझे इस पर यकीन नहीं है, लेकिन शायद आप सही हैं: ऐसा हो सकता है कि पहले भी cमूल्यांकन किया जाए, भले ही अल्पविराम सहयोगी हो। (a, b)
CygnusX1

1
एक क्लास कंस्ट्रक्टर में अल्पविराम द्वारा अलग किए गए इनिशियलाइज़ेशन लिस्ट में बस एक छोटी सी टिप्पणी, सूची में स्थिति के अनुसार क्रम निर्धारित नहीं होता है। आदेश वर्ग की घोषणा की स्थिति से निर्धारित होता है। जैसे पहले struct Foo { Foo() : a(5), b(3) {} int b; int a; }विकसित होता है । यह महत्वपूर्ण है अगर आपकी सूची ऐसा है :। b को 5 पर सेट नहीं किया जाएगा, बल्कि इसके बारे में अनइंस्टाल्यूटेड वैल्यू है, जिसके बारे में आपका कंपाइलर चेतावनी दे भी सकता है और नहीं भी। b(3)a(5)Foo() : a(5), b(a) {}
जोनाथन गवरीच

मैं हाल ही में दो झांकियों के साथ अल्पविराम ऑपरेटर के साथ आया था, एक संख्या का मूल्यांकन और त्यागने का क्या मतलब है?
एरोन फ्रेंके

मुझे नहीं लगता कि कोई भी इसका जवाब दे सकता है। आपको इसे एक संदर्भ में दिखाना होगा। शायद एक अलग सवाल?
साइग्नसएक्स 1

38

का मान aहोगा b, लेकिन अभिव्यक्ति का मूल्य होगा c। यह है

d = (a = b, c);

ए के बराबर होगा b, और के dबराबर होगा c


19
लगभग सही है। कथन में मूल्य नहीं हैं, भाव हैं। उस अभिव्यक्ति का मान c है।
लियोन टिम्मरमैन

इसके बजाय इसका उपयोग क्यों किया जाता है a = b; d = c;?
एरोन फ्रेंके

इससे मुझे समझ में आ गया कि लोग किस दुष्प्रभाव की बात कर रहे थे।
Shoelace


2

वसीयत का मूल्य b के बराबर होगा, क्योंकि अल्पविराम ऑपरेटर के असाइनमेंट संचालक की तुलना में कम है।


2

हाँ, कोमा संचालक के पास असाइनमेंट ऑपरेटर की तुलना में कम पूर्वता है

#include<stdio.h>
int main()
{
          int i;
          i = (1,2,3);
          printf("i:%d\n",i);
          return 0;
}

आउटपुट: i = 3
क्योंकि अल्पविराम ऑपरेटर हमेशा सही मान देता है।
संचालक ऑपरेटर के साथ अल्पविराम ऑपरेटर के मामले में:

 int main()
{
      int i;
      i = 1,2,3;
      printf("i:%d\n",i);
      return 0;
}

Ouput: i = 1
जैसा कि हम जानते हैं कि अल्पविराम ऑपरेटर में असाइनमेंट की तुलना में कम पूर्वता है .....


तो दूसरा उदाहरण i = 1;उस रेखा पर होने से कैसे अलग है ?
एरोन फ्रेंके

-3

पहली चीजें पहले: कोमा वास्तव में एक ऑपरेटर नहीं है, संकलक के लिए यह सिर्फ एक टोकन है जो अन्य टोकन के संदर्भ में एक अर्थ प्राप्त करता है

इसका क्या मतलब है और परेशान क्यों है?

उदाहरण 1:

एक ही संदर्भ में एक ही टोकन के अर्थ के बीच के अंतर को समझने के लिए हम इस उदाहरण पर एक नज़र डालते हैं:

class Example {
   Foo<int, char*> ContentA;
}

आमतौर पर एक सी ++ शुरुआत करने वाले सोचते हैं कि यह अभिव्यक्ति चीजों की तुलना कर सकती है / लेकिन यह पूरी तरह से गलत है, उपयोग के संदर्भ में इसका अर्थ है <, >और ,टोकन चित्रण है।

ऊपर दिए गए उदाहरण की सही व्याख्या निश्चित रूप से यह है कि यह एक टेम्पलेट का एक उदाहरण है।

उदाहरण 2:

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

for(a=5,b=0;a<42;a++,b--)
   ...

अल्पविराम का अर्थ उपयोग के संदर्भ पर निर्भर करता है, यहां यह forनिर्माण का संदर्भ है ।

संदर्भ में अल्पविराम का वास्तव में क्या मतलब है?

इसे और भी अधिक जटिल बनाने के लिए (हमेशा C ++ में) कॉमा ऑपरेटर को खुद ही ओवरलोड किया जा सकता है ( जो कि बाहर की ओर इशारा करने के लिए कोनराड रूडोल्फ के लिए धन्यवाद )।

प्रश्न पर वापस आने के लिए, कोड

a = b, c;

संकलक के लिए कुछ पसंद है

(a = b), c;

क्योंकि प्राथमिकता के =टोकन / ऑपरेटर की प्राथमिकता से अधिक है ,टोकन।

और इस तरह के संदर्भ में व्याख्या की है

a = b;
c;

(ध्यान दें कि व्याख्या संदर्भ पर निर्भर करती है, यहां यह न तो एक फ़ंक्शन / विधि कॉल या एक टेम्पलेट अस्थिरता है।)


1
यकीन है कि यह है, शायद मैं गलत शब्दावली का इस्तेमाल करता था (
लेक्सर के

2
जैसा कि एक ऑपरेटर (सिक) के साथ काम करता है , कॉमा वास्तव में एक ऑपरेटर है।
ड्रैगनलैड

2
यह मानते हुए कि अगर कॉमा टोकन दिया गया है तो कॉमा ऑपरेटर के रूप में पहचाना जाता है (उदाहरण के लिए, तर्क के विभाजक के विपरीत) अपने आप पर एक चुनौती हो सकती है, यह सवाल विशेष रूप से अल्पविराम ऑपरेटर के बारे में है ।
साइग्नसएक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.