2010-07-19 12 views
8

संभव डुप्लिकेट:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)पोस्ट-बढ़ते क्रम में ऑपरेटर: अनपेक्षित व्यवहार

मेरे कोड इस प्रकार है:

#include <stdio.h> 
int main() 
{ 
    int x = 10, y = 0; 
    x = x++; 
    printf("x: %d\n", x); 
    y = x++; 
    printf("y: %d\n", y); 
} 

बाद वेतन वृद्धि की प्रकृति को देखते हुए, मैं निम्नलिखित आउटपुट की अपेक्षा करेगा:

x: 10 
y: 10 

मेरा तर्क यह है कि लाइन 5, x में वृद्धि के बाद अपने शुरुआती मूल्य को असाइन किया जाना चाहिए।

इसके बजाय, तथापि, मैं इस मिल:

x: 11 
y: 11 

विधानसभा में खुदाई, यह मेरे लिए एक विचार पसंद की तरह दिखता है:

LCFI2: 
     movl $10, -4(%rbp) // this is x 
     movl $0, -8(%rbp) // this is y 
     incl -4(%rbp)  // x is simply incremented 
     movl -4(%rbp), %esi 
     leaq LC0(%rip), %rdi 
     movl $0, %eax 
     call _printf 
     movl -4(%rbp), %eax // now x is saved in a register, 
     movl %eax, -8(%rbp) // copied to y, 
     incl -4(%rbp)  // and finally incremented 
     movl -8(%rbp), %esi 
     leaq LC1(%rip), %rdi 
     movl $0, %eax 
     call _printf 

यहाँ क्या हो रहा है? क्या जीसीसी मुझे खुद से बचाने की कोशिश कर रहा है? मेरे पास भाषा संदर्भ आसान नहीं है लेकिन मैंने सोचा होगा कि यह इच्छित अर्थशास्त्र को तोड़ देता है।

+0

घृणित कामों रूप में लिखा जाएगा !!! –

+0

http://en.wikipedia.org/wiki/Sequence_point – Ken

+0

बुरे पुराने दिनों में, कुछ भाषाओं में 'ए = 1 + ए' एक खदान था जो सभी नई बग चलती थीं। –

उत्तर

13

व्यवहार को अपरिभाषित किया गया है क्योंकि x = x++ में कोई हस्तक्षेप अनुक्रम बिंदु नहीं है, उदाहरण के लिए देखें। C FAQ

+0

धन्यवाद! मुझे पहले अनुक्रम बिंदुओं के बारे में पता नहीं था। – danben

4

यह सी भाषा द्वारा अनिर्धारित छोड़ दिया गया है जब वास्तव में एक पोस्ट/प्री-इन/कमी होती है। इस प्रकार, x = x++ जैसे बयान अच्छी तरह से गठित नहीं होते हैं - उनसे बचें।

+1

अधिक सटीक आपको अभिव्यक्ति में एक से अधिक बार एक चर को संशोधित करने की अनुमति नहीं है। 6।5/2: * "पिछले और अगले अनुक्रम बिंदु के बीच किसी ऑब्जेक्ट में अभिव्यक्ति के मूल्यांकन द्वारा सबसे अधिक बार संग्रहीत मूल्य संशोधित किया जाएगा।" * – sth

+2

@sth: अधिक सटीक, "अनुक्रम बिंदुओं के बीच एक से अधिक"। अभिव्यक्ति के लिए एक अनुक्रम बिंदु होना संभव है, जिसमें एक बार एक चर को एक से अधिक संशोधित करना ठीक है। उदाहरण के लिए, '&&', '||' और अल्पविराम ऑपरेटर सभी एक ही अभिव्यक्ति के भीतर अनुक्रम बिंदु बना सकते हैं। –

+0

@sth: यहां तक ​​कि _more ok_, यह कोडर पर एक सीमा नहीं है, यह चरम पर एक सीमा है। आपका बयान है कि आपको "अनुमति नहीं है ..." बिल्कुल सही नहीं है। आपको _are_ की अनुमति है, यह करने के लिए बस एक बहुत ही मूर्ख चीज है :-) – paxdiablo

1

जब आपके पास:

a = b++; 

क्या हो रहा है कि ख एक को बचाया जाता है और बाद असाइनमेंट किया जाता है ख एक के बाद वृद्धि की जाती है है। तो अगर आप कार्य करें:

x = x ++; 

और पहले x 10 था कि क्या होगा 10 x में सहेज लिया जाएगा और उसके बाद (करने से पहले अपने printf किया जाता है) x 11. क्यों 11 मुद्रित किया जाता है यही कारण है कि करने के लिए एक के बाद वृद्धि की जाती है है।

2

मानक एक तरफ (चूंकि यह मानक के संबंध में अपरिभाषित है), जिस तरह से यह चल रहा है वैसे ही जिस तरह से मैंने इसकी अपेक्षा की थी।

अंगूठे का मेरा नियम है कि x++ के साथ एक पंक्ति के लिए, आप x साथ x++ स्थानापन्न और निम्न पंक्ति (या पूर्व वेतन वृद्धि के लिए पूर्ववर्ती लाइन) पर x += 1 डाल है।

अंगूठे का नियम है कि के बाद, अपने कोड

#include <stdio.h> 
int main() 
{ 
    int x = 10, y = 0; 
    x = x; // x: 10 
    x += 1; // x: 11 
    printf("x: %d\n", x); 
    y = x; // y: 11 
    x += 1; // x: 12 
    printf("y: %d\n", y); 
} 
संबंधित मुद्दे