2009-10-22 8 views
5

सी ++ और सी # में कोड का यह उदाहरण अलग-अलग व्यवहार क्यों कर रहा है।एक कथन में इंडेक्स, असाइनमेंट और वृद्धि सी ++ और सी # में अलग-अलग व्यवहार करती है। क्यूं कर?

[सी ++ उदाहरण]

int arr[2]; 
int index = 0; 
arr[index] = ++index; 

जिनमें से परिणाम आगमन हो जाएगा [1] = 1;

[सी # उदाहरण]

int[] arr = new int[2]; 
int index = 0; 
arr[index] = ++index; 

जिनमें से परिणाम आगमन हो जाएगा [0] = 1;

मुझे यह बहुत अजीब लगता है। निश्चित रूप से दोनों भाषाओं के लिए इसे अलग-अलग लागू करने के लिए कुछ तर्क होना चाहिए? मुझे आश्चर्य है कि सी ++/सीएलआई आउटपुट क्या होगा?

+0

ठीक है, jynx, दोस्तों। ;) – hobbs

उत्तर

11

जैसा कि अन्य ने ध्यान दिया है, इस कोड का व्यवहार सी/सी ++ में अपरिभाषित है। आप जो भी परिणाम प्राप्त कर सकते हैं।

आपके सी # कोड का व्यवहार सी # मानक द्वारा कड़ाई से परिभाषित है।

निश्चित रूप से दोनों भाषाओं के लिए इसे अलग-अलग लागू करने के लिए कुछ तर्क होना चाहिए?

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

सी # के डिजाइनरों का मानना ​​नहीं है कि सरल अभिव्यक्तियों के अपरिभाषित व्यवहार एक अच्छी बात है, और इसलिए हमने कड़ाई से परिभाषित किया है कि इस तरह के अभिव्यक्तियों का क्या अर्थ है। हम संभवतः प्रत्येक सी ++ कंपाइलर के साथ सहमत नहीं हो सकते हैं क्योंकि विभिन्न सी ++ कंपाइलर्स आपको इस तरह के कोड के लिए अलग-अलग परिणाम देते हैं, और इसलिए हम उन सभी के साथ सहमत नहीं हो सकते हैं।

क्यों सी ++ के डिजाइनरों का मानना ​​है कि इस तरह के सरल अभिव्यक्तियों को अनिश्चित व्यवहार के लिए छोड़ना बेहतर है, ठीक है, आपको उनमें से एक से पूछना होगा। मैं निश्चित रूप से कुछ अनुमान लगा सकता हूं, लेकिन वे केवल शिक्षित अनुमान होंगे।

मैंने इस तरह के मुद्दे के बारे में कई ब्लॉग लेख लिखे हैं; मेरा सबसे हालिया एक लगभग कोड है जो आप यहां उल्लेख करते हैं।कुछ लेख आप भी पढ़ सकते हैं:

लिए कैसे सी # के डिजाइन सूक्ष्म कीड़े के उन्मूलन को प्रोत्साहित करती है:

http://blogs.msdn.com/ericlippert/archive/2007/08/14/c-and-the-pit-of-despair.aspx

वास्तव में सी # में पूर्वता, संबद्धता, और निष्पादन का आदेश के बीच संबंध क्या है?

http://blogs.msdn.com/ericlippert/archive/2008/05/23/precedence-vs-associativity-vs-order.aspx

किस क्रम में अनुक्रमण, असाइनमेंट और वेतन वृद्धि के साइड इफेक्ट होता है?

http://blogs.msdn.com/ericlippert/archive/2009/08/10/precedence-vs-order-redux.aspx

+0

धन्यवाद। मैं लेख पढ़ूंगा। –

+0

यह सी ++ में अपरिभाषित है क्योंकि यह सी में भी अपरिभाषित है। स्पष्ट रूप से, मानक सी संकलक मानक को अपनाए जाने से पहले अलग-अलग चीजें करते थे और इसे अनिर्धारित छोड़कर एकमात्र विकल्प विकल्प था, आईएमएचओ। –

3

उसी असाइनमेंट के अंदर इंडेक्स और ++ इंडेक्स का उपयोग करने का व्यवहार सी ++ में निर्दिष्ट नहीं है। आप बस ऐसा नहीं कर सकते: arr[index] = index + 1 लिखें और उसके बाद अपना चर बढ़ाएं। उस मामले के लिए, मेरी मशीन पर मेरे सी ++ कंपाइलर के साथ मैं एआर [0] = 1 देखता हूं, और arr [1] छूटा हुआ है।

+6

यह अनिर्दिष्ट से भी बदतर है, यह वास्तव में अपरिभाषित व्यवहार है। –

+0

बेशक, मुझे यही लिखा जाना चाहिए था (यह * निर्दिष्ट * के रूप में * अपरिभाषित * ;-) जब आप पूरी सुबह डिबगिंग खर्च करते हैं तो सीधे दिमाग नहीं रख सकता ... (मुझे भी gdb में एक बग मिला!) –

4

आपका सी ++ कोड वास्तव में कुछ भी कर सकता है। arr[index] = ++index; अपरिभाषित व्यवहार का आह्वान करता है।

0

सी ++ संस्करण का परिणाम हमेशा लिखना नहीं होगा जैसा कि आप अपरिभाषित व्यवहार का आह्वान कर रहे हैं। सी ++ में आपको अपरिभाषित व्यवहार मिलेगा यदि आप किसी अभिव्यक्ति में चर के मान का उपयोग करते हैं, तो उस चर को एक ही अभिव्यक्ति में भी संशोधित किया जाता है जब तक कि यह मान पढ़ने के लिए मान को निर्धारित करने का हिस्सा न हो, या अभिव्यक्ति में अनुक्रम होता है पढ़ने और लिखने के बीच पर इंगित करें।

अपने अभिव्यक्ति में, आप index का मूल्य पढ़ रहे हैं निर्धारित करने के लिए जहां = के दाहिने हाथ की ओर का परिणाम आवंटित करने के लिए, लेकिन दाहिने हाथ उप अभिव्यक्ति भी index संशोधित करता है।

1

सी ++ के मामले में, कम से कम, आप पूर्ववर्ती व्यवहार और index का उपयोग बिना अनुक्रम बिंदु के अपरिभाषित व्यवहार का आह्वान कर रहे हैं। आप चेतावनी के साथ जीसीसी है कि कोड को खिलाने के सक्षम होने पर यह लिखा होगा:

preinc.cpp:6: warning: operation on ‘index’ may be undefined 

मेरा अनुमान है कि यह है कि यह सी # में रूप में अच्छी तरह अपरिभाषित है, लेकिन मैं भाषा नहीं जानता। सी और सी ++ के लिए कम से कम हालांकि, जवाब यह है कि संकलक कुछ भी गलत होने के बिना कर सकता है क्योंकि आपका कोड गलत है। संगत परिणामों का उत्पादन करने के लिए विभिन्न कंपाइलरों (या यहां तक ​​कि एक ही कंपाइलर) के लिए कोई दायित्व नहीं है।

+0

एक जिज्ञासा के रूप में, जी ++ 4.4.1 सी # के रूप में व्यवहार करता है, सेटिंग सरणी [0] = 1. – hobbs

+1

_ पूर्व परिभाषित व्यवहार_ का अर्थ है कि यह 'सरणी [1] = 1' सेट कर सकता है या' सरणी [4711] = 42' सेट कर सकता है, अपनी हार्ड मिटाएं डिस्गर मौजूद है या नहीं, यह निर्भर करता है कि यह एक गंवा है, यह चंद्रमा के चरण के आधार पर 42 वें समय तक चलता है, आपकी प्रेमिका आपको कितनी पसंद करती है, या आप अपनी मां के लिए बुरा हो। यह कहने का कोई मतलब नहीं है "कंपाइलर एक्स, संस्करण वाई, क्या यह _this_ रास्ता है", क्योंकि आप कभी नहीं जानते। (http://stackoverflow.com/questions/1553382/1553407#1553407) – sbi

+4

यह * सी # में * निश्चित रूप से परिभाषित * है। हम सरल अभिव्यक्तियों के इस पागल व्यवसाय के लिए नहीं जाते हैं जिसका अर्थ नहीं है लेकिन संकलक उन्हें वैसे भी लेता है और कुछ पागल चीज करता है। हमें कुछ क्रेडिट दें! –

1

नोट: @Eric Lippert के answer के अनुसार, व्यवहार सख्ती से सी # के लिए परिभाषित किया है, तो मुझे इस पर मेरा उत्तर reword जाने है।

इस कोड:

arr[index] = ++index; 

भले ही सी # संकलक वास्तव में जानता है कि यह किस क्रम में कैसे मूल्यांकन करने के लिए पढ़ना कठिन है। अकेले इस कारण से इसे टालना चाहिए।

सी # ऑपरेटरों पर MSDN page अब तक यह इंगित करता है कि यह व्यवहार अपरिभाषित हो सकता है, भले ही एरिक बताता है कि यह नहीं है। तथ्य यह है कि दस्तावेज के कई स्रोत (मैं इस पर एरिक पर भरोसा करता हूं) इसे अलग करता है यह भी बताता है कि यह कुछ अकेला छोड़ सकता है।

+2

यह सी # में उल्लिखित नहीं है, यह सख्ती से परिभाषित किया गया है। ऊपर देखो। –

+2

शायद किसी को एमएसडीएन दस्तावेज जाना चाहिए और अपडेट करना चाहिए? –

+1

पवित्र भलाई, वह पृष्ठ चॉकलेट त्रुटियों का पूरा है। मैं तुरंत प्रलेखन प्रबंधक के साथ एक बात करेंगे। उसे मेरी जानकारी मे लाने के लिए धन्यवाद। –

-1

सी # में सूचकांक एक मान प्रकार है, जिसका अर्थ यह है कि जब आप उस पर संचालन करते हैं तो आप मूल्य का एक नया उदाहरण वापस कर देते हैं।

आप एक ऑपरेटर के बजाय एक प्रक्रिया के रूप में यह कल्पना करते हैं, तो प्रक्रिया इस प्रकार दिखाई देगा:

public int Increment(int value) 
{ 
    int returnValue=value+1; 
    return returnValue; 
} 

सी ++, तथापि, वस्तु के संदर्भ पर काम करता है, इसलिए प्रक्रिया दिखाई देगा:

int Increment(int &value) 
{ 
    value=value+1; 
    return value; 
} 

नोट: यदि आप किसी ऑब्जेक्ट पर ऑपरेटर को लागू कर रहे थे (++ ऑपरेटर ओवरलोडेड कहें) तो सी # सी ++ की तरह व्यवहार करेगा, क्योंकि ऑब्जेक्ट प्रकार संदर्भ के रूप में पास किए जाते हैं।

+0

क्या आप सी # ++ इंडेक्स में कह रहे हैं इंडेक्स को संशोधित नहीं करता है? – Henrik

+0

नहीं, मैं बस नींद आ गया था क्योंकि मैं समझाने की कोशिश कर रहा था और सही नहीं सोच रहा था –

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