2010-05-28 11 views
6

नीचे दिया गया कोड इस अंतर को दर्शाता है:क्या सी ++ में ऑपरेटर प्राथमिकता पॉइंटर्स और इटरेटर के लिए भिन्न है?

#include <iostream> 
#include <string> 

int main() 
{ 
     char s[] = "ABCD"; 
     std::string str(s); 

     char *p = s; 
     while(*p) { 
       *p++ = tolower(*p);   // <-- incr after assignment 
     } 
     std::cout << s << std::endl; 

     std::string::iterator it = str.begin(), end = str.end(); 
     while(it != end) { 
       *it++ = tolower(*it);  // <-- incr before assignment ? 
     } 
     std::cout << str << std::endl; 

     return 0; 
} 

यह आउटपुट उत्पन्न करता है:

abcd 
bcd 

अगर हम असाइनमेंट ऑपरेशन और वृद्धि ऑपरेटर को अलग करते हैं:

while(it != end) { 
    *it = tolower(*it);  // <-- incr before assignment ? 
    it++; 
} 

आउटपुट की अपेक्षा की जाएगी।

मूल कोड के साथ क्या गलत है?

$ g++ --version 
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125) 
Copyright (C) 2004 Free Software Foundation, Inc. 

उत्तर

9

समस्या यह है कि operator= के तर्कों के मूल्यांकन के आदेश अनिर्दिष्ट है। यह सी ++ मानक 5.2.2/8 के अनुसार है। निम्नलिखित पर विचार करें:

*it++ = tolower(*it); 

operator=(*it++, tolower(*it)); 

अब *it++tolower(*it) से पहले परिकलित किया जा सकता है और इसके विपरीत के बराबर है।

+1

यह अनिर्दिष्ट व्यवहार से भी बदतर है, मूल अभिव्यक्ति में अपरिभाषित व्यवहार है। Subxpressions का एक संभावित क्रम है जहां 'यह ++' मूल्यांकन किया जाता है (यानी 'इसे' लिखना 'इससे ​​पहले' '' 'के लिए पैरामीटर मूल्यांकन में पढ़ा जाता है, जिसमें कोई हस्तक्षेप अनुक्रम बिंदु नहीं होता है। ऐसा हो सकता है कि असाइनमेंट ऑपरेटर फ़ंक्शन कॉल है या नहीं। किसी भी तरह से 5 [expr], पैरा 8 पुष्टि करता है कि यह अपरिभाषित व्यवहार है। –

2
*it++ = tolower(*it); 
*p++ = tolower(*p); 
इन पंक्तियों के

दोनों अपरिभाषित व्यवहार आह्वान। आप एकल कथन में एक से अधिक बार एक चर के मान को संशोधित नहीं कर सकते (++ एक बार संशोधित करता है, ऑपरेटर = दो बार संशोधित करता है)।

तो तथ्य यह है कि आपको अलग-अलग मूल्य मिलते हैं, यह आश्चर्यजनक नहीं है।

+0

'ऑपरेटर ++' और 'ऑपरेटर = 'प्रत्येक मामले में दो अलग-अलग चरों पर लागू होते हैं। कोई यूबी नहीं है। –

+0

@ किरील वी। लिडविंस्की: पॉइंटर और इटरेटर मामले दोनों के लिए अपरिभाषित व्यवहार है क्योंकि संचालन की संभावित अनुक्रमितता थी, 'it' (या' p') के मान के पढ़ने के बीच कोई हस्तक्षेप अनुक्रम बिंदु नहीं था। असाइनमेंट के आरएचएस पर '*' ऑपरेटर और असाइनमेंट के एलएचएस पर वृद्धि ऑपरेशन के लिए। –

+0

जो कुछ भी मामला है, रेखाएं निश्चित रूप से उलझन में हैं और मैं इसे वैसे भी लिखना नहीं चाहूंगा :-) –

2

व्याकरण पॉइंटर्स और इटरेटर के लिए बिल्कुल वही काम करता है। ऑपरेटरों द्वारा निहित संचालन वर्ग प्रकार की वस्तुओं (जैसे अधिकांश इटरेटर) के लिए फ़ंक्शन कॉल में बदल जाते हैं।

आपके कोड के साथ समस्या ऑपरेटर प्राथमिकता के साथ नहीं है, हालांकि इन दोनों पंक्तियों में वृद्धि कार्य के बीच कोई अनुक्रम नहीं है और उसी चर के दूसरे पढ़ने को कथन में कहीं और बढ़ाया गया है। इस वजह से, आपके पास अपरिभाषित व्यवहार है, इसलिए वह आपके कार्यक्रम से कोई भी व्यवहार देख सकता है जिसमें आप देख रहे हैं।

*p++ = tolower(*p); 

*it++ = tolower(*it); 

आपको इस कथन को एक तरीके से सुधारने की आवश्यकता है जिसमें अनुक्रम परिभाषित किया गया है। मुझे लगता है कि आप ऐसा कुछ चाहते हैं।

char c = tolower(*p); 
*p++ = c; 
+0

+1: आपका एडन काम करता है, लेकिन मैंने अस्पष्टता की अस्पष्टता क्यों की है –

+0

डाउनवोट के लिए तर्क, कोई भी? अच्छे सुझाव के लिए –

+0

+1। अंत में यह गलत सुझाव हो सकता है, लेकिन यह सहायक है। मानक के लिंक जोड़ने पर विचार करें। –

संबंधित मुद्दे