2009-08-11 3 views
12

आज मैं Eric Lippert द्वारा एक लेख पार किया जहां वह ऑपरेटरों की प्राथमिकता और मूल्यांकन के आदेश के बीच मिथक को साफ़ करने की कोशिश कर रहा था।
int [] arr = {0}; int value = arr [arr [0] ++]; मान = 1?

 int[] arr = {0}; 
     int value = arr[arr[0]++]; 

अब जब मैं चर मूल्य के मूल्य के बारे में सोचते हैं, मैं बस इसे एक होने की गणना: अंत में दो कोड स्निपेट है कि मुझे उलझन में मिला रहे थे, यहाँ पहली टुकड़ा है। यहां बताया गया है कि मैंने सोचा कि यह काम कर रहा है। इसके अंदर एक आइटम के साथ पूर्णांक की एक सरणी के रूप में

  1. पहले घोषित आगमन; यह आइटम का मान 0.
  2. दूसरा इस मामले में में arr [0] --0 का मान प्राप्त करें।
  3. तीसरा आगमन (जो अभी भी 0) [चरण 2 का मूल्य ] का मूल्य आगमन --gets [0] फिर --still 0.
  4. चौथे चरण के मूल्य निर्दिष्ट मिल 3 (0) परिवर्तनीय मूल्य के लिए। --value = 0 अब
  5. कदम का मूल्य में जोड़े 2 1 --Now आगमन [0] = 1.

जाहिर है यह गलत है। मैंने सी # चश्मा को कुछ स्पष्ट बयान के लिए खोजने की कोशिश की कि जब वास्तव में वृद्धि हो रही है, लेकिन कोई भी नहीं मिला। यहाँ

int[] data = { 11, 22, 33 }; 
int i = 1; 
data[i++] = data[i] + 5; 

अब है मैं कैसे लगता है कि इस कार्यक्रम सरणी घोषित करने और मैं करने के लिए 1 बताए --after निष्पादित करेंगे:
दूसरा टुकड़ा विषय पर एरिक के blog post की एक टिप्पणी से है। [Plz मुझे साथ सहन]

  1. डेटा प्राप्त करें [i] --1
  2. चरण 1 मूल्य 5 --6
  3. असाइन आंकड़ों के [i] (का मूल्य है जो में जोड़े अभी भी 1) कदम का मूल्य 2 --data [i] = 6
  4. वृद्धि मैं - मैं = 2

मेरी समझ के अनुसार, इस सरणी अब मान {11, 27 को शामिल करना चाहिए, 33}। हालांकि, जब मैंने सरणी मानों को मुद्रित करने के लिए प्रेरित किया तो मुझे मिला: {11, 38, 33}। इसका मतलब है कि पोस्ट वृद्धि सरणी को संदर्भित करने से पहले हुई थी!
कैसे आते हैं? क्या यह पोस्ट वृद्धि पोस्ट नहीं होने वाली है? यानी सब कुछ के बाद होता है।
मुझे क्या याद आ रही है?

+0

आपका पांचवें चरण के रूप में अपने बयान के बारे में सोचना है वैसे भी सही नहीं है। "चरण 2 1 के मूल्य में जोड़ें - अब तीर [0] = 1." सरणी से लिया/कॉपी किया गया मान एक के साथ बढ़ाया जाता है, लेकिन ** ** में मान ** सरणी को छुआ नहीं जाता है। तो कथन arr [0] = 1 गलत है। चरण 5 पर एआर [0] = 1 से प्रतिलिपि मूल्य। – Gertjan

+0

ठीक है, मैंने अभी कोड चलाया है और मुझे पहले जवाब के लिए मान 0 और दूसरा के रूप में {11,27,33} मिला है ... क्या यह चीज़ संकलक विशिष्ट है ? – bubblegum

+1

@Swabha आप सुनिश्चित हैं कि आप सी # का उपयोग कर रहे हैं? – Galilyou

उत्तर

16

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

दूसरे शब्दों में, किसी भी अभिव्यक्ति E के लिए, ई ++ (यदि कानूनी) (छद्म कोड) की तरह कुछ का प्रतिनिधित्व करता है:

T tmp = E; 
E += 1; 
return tmp; 

कि ई का मूल्यांकन ++ के सभी हिस्सा है, से पहले कुछ और मूल्यांकन किया जाता है।

अधिक जानकारी के लिए सी # 3.0 spec के सेक्शन 7.5.9 देखें।


साथ ही, काम के संचालन जहां एलएचएस एक चर के रूप में वर्गीकृत किया जाता है (इस मामले में के रूप में) के लिए, एलएचएस से पहले आरएचएस मूल्यांकन किया जाता है मूल्यांकन किया जाता है।

तो अपने उदाहरण में:

int[] data = { 11, 22, 33 }; 
int i = 1; 
// Work out what the LHS is going to mean... 
int index = i; 
i++; 
// We're going to assign to data[index], i.e. data[1]. Now i=2. 

// Now evaluate the RHS 
int rhs = data[i] + 5; // rhs = data[2] + 5 == 38 

// Now assign: 
data[index] = rhs; 

इस के विशिष्टीकरण के प्रासंगिक बिट खंड 7.16.1 (सी # 3.0 कल्पना) है:

int[] data = { 11, 22, 33 }; 
int i = 1; 
data[i++] = data[i] + 5; 

के बराबर है।

+3

वह, और अभिव्यक्ति (असाइनमेंट सहित) का मूल्यांकन बाएं से दाएं किया जाता है, इसके अलावा जब ऑपरेटर प्राथमिकता अन्यथा निर्देशित करती है। इसलिए डेटा [i ++] (असाइनमेंट के बायीं तरफ) का मूल्यांकन डेटा [i] दाएं हाथ से पहले किया जाता है। – LBushkin

+0

@LBushkin: मुझे लगता है कि जब आप टिप्पणी कर रहे थे तो मैं वास्तव में उस उद्देश्य के लिए संपादन कर रहा था :) –

+0

@LBushkin गलत। माइक्रोसॉफ्ट स्पष्ट रूप से कहता है कि असाइनमेंट (=) और टर्नरी (? :) ऑपरेटरों दोनों को दाएं से बाएं से हल किया गया है। –

2
data[i++] // => data[1], then i is incremented to 2 

data[1] = data[2] + 5 // => 33 + 5 
+0

मैं आपसे असहमत हूं। कार्यान्वयन का कहना है कि असाइनमेंट ऑपरेटर सबसे कम प्राथमिकता है और दाएं से बाएं से हल किया गया है। भाषा चश्मे के अनुसार, लड़का अपनी धारणाओं पर सही है। http://msdn.microsoft.com/en-us/library/aa691323(VS.71).aspx –

+2

@Leahn Novash: आप मूल्यांकन आदेश के साथ फिर से उलझन में सहयोगी हैं। "ए = बी = सी" सही सहयोगी है "ए = (बी = सी)", लेकिन यह मूल्यांकन आदेश के बारे में कुछ भी नहीं कहता है। सी # में मूल्यांकन आदेश हमेशा बाएं से दाएं है। – Daniel

+0

मैंने विनिर्देशों को और अधिक सावधानी से पढ़ा है। मुझे सही साबित होना है। –

-4

कारण हो सकता है कुछ compilers मैं ++ मैं होने की ++ का अनुकूलन है। अधिकांश समय, अंतिम परिणाम वही होता है, लेकिन ऐसा लगता है कि संकलक गलत होने पर मुझे उन दुर्लभ मौकों में से एक माना जाता है।

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

+4

i ++ और ++ मैं अलग हैं और विभिन्न तरीकों से उपयोग किया जाता है। कोई संकलक जो I ++ से ++ में परिवर्तित करता है, मैं कई डेवलपर के क्रोध को आमंत्रित करता हूं। – NickAldwin

+1

सौभाग्य से, सी # इसके व्यवहार को इसके बजाय बेहतर तरीके से परिभाषित करता है। –

+1

मैं मानता हूं कि कंपाइलर, गिटर, या प्रोसेसर ऑप्टिमाइज़ेशन हो सकते हैं, लेकिन ऐसा तब होगा जब ऑप्टिमाइज़ेशन के परिणाम केवल एक थ्रेडेड एप्लिकेशन पर वांछित परिणाम से अलग नहीं हैं: http://blogs.msdn.com/ericlippert /archive/2009/08/10/precedence-vs-order-redux.aspx – Galilyou

0

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

ऐसा नहीं होगा, तो आप

data[i++] = data[i++] + data[i++] + data[i++] + 5 

लिख सकता है ऐसा लगता है कि आप कहते हैं, तो आप वेतन वृद्धि ऑपरेटर, क्योंकि यह वास्तव में कुछ भी ऐसा नहीं करता है को दूर कर सकता है अनुदेश मैं सूचना में, हो सकता है ।

5

पहले स्निपेट के लिए, अनुक्रम है:

आप के रूप में
  1. प्रचार आगमन वर्णित:
  2. आगमन का मान प्राप्त [0], जो कि 0
  3. वृद्धि के आगमन [0 मूल्य ] 1.
  4. के आगमन [value] जो आगमन है (# 2 का परिणाम होती है) [0], जो (प्रति # 3) है 1.
  5. स्टोर कि value में परिणाम।
  6. मूल्य = 1

दूसरा स्निपेट के लिए, मूल्यांकन अभी भी बाएँ-से-सही है।

  1. हम परिणाम कहां संग्रहीत कर रहे हैं? डेटा [i ++] में, जो डेटा [1] है, लेकिन अब i = 2
  2. हम क्या जोड़ रहे हैं?डेटा [i] + 5, जो अब डेटा है [2] + 5, जो 38 है।

गायब टुकड़ा यह है कि "पोस्ट" का मतलब "सब कुछ के बाद" नहीं है। इसका मतलब है "तुरंत उस चर के वर्तमान मूल्य को पुनर्प्राप्त करने के बाद।" कोड की एक पंक्ति "बीच में" होने वाली एक पोस्ट वृद्धि पूरी तरह से सामान्य है।

0

आप तीन चरणों में कार्य के बारे में सोच करने के लिए है:

  1. मूल्यांकन बाएं हाथ की ओर (= पता नहीं है जहां मूल्य संग्रहित किया जाना चाहिए प्राप्त)
  2. मूल्यांकन दाहिने हाथ की ओर
  3. कदम से मान निर्दिष्ट करें कदम 1.

से स्मृति स्थान के लिए 2 आप

की तरह कुछ है, तो

फिर ए() पहले चलाएगा, फिर सी() चलाएगा, और फिर संपत्ति सेटर बी चलाएगा।

अनिवार्य रूप से, आप

StoreInArray(data, i++, data[i] + 5); 

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

  • कोई संबंधित समस्या नहीं^_^