"X = x ++" के बाद x क्या है?


285

ऐसा होने पर (पर्दे के पीछे) क्या होता है?

int x = 7;
x = x++;

वह यह है कि, जब एक चर को एक बयान में पोस्ट वृद्धि और खुद को सौंपा जाता है? मैंने इसे संकलित और निष्पादित किया। पूरे बयान के बादx भी 7 है । मेरी किताब में, यह कहते हैं कि वेतन वृद्धि हुई है!x


9
यह कोशिश करें: int x = 7; x = ++x;बेशक, अभी भी भयानक कोड है, आपको आश्वस्त होने की आवश्यकता नहीं है। int x = 7; x++;पर्याप्त है।
stivlo

7
यह एक बहुत ही बुरा अभ्यास है, जिस लाइन का आप इसे इस्तेमाल करते हैं, उसी लाइन में वृद्धि नहीं करते।
यूसुफ

5
मैं उपयोग करना पसंद करूंगा x += 1, शायद छोरों को छोड़कर। for(int x=0; x<7; x++)
Svish

2
@andyortlieb कोई वस्तु नहीं है, बस एक मूल मूल्य है।
फोरट्रान

जवाबों:


301

xबढ़ जाता है। लेकिन आप अपने आप में पुराने मूल्य को xवापस सौंप रहे हैं ।


x = x++;
  1. x++वेतन वृद्धि xऔर उसका पुराना मूल्य लौटाता है।
  2. x = पुराने मान को स्वयं पर वापस करता है।

तो अंत में, xअपने प्रारंभिक मूल्य को वापस सौंपा जाता है।


3
फिर, आप x = ++ x के बारे में क्या कहेंगे;
हिशाम मुनीर

3
xउस मामले में पढ़ने से पहले @HishamMuneer पहले बढ़ जाता है, इसलिए आप समाप्त करते हैं x + 1

@ हिशमुनियर यह बहुत देर हो चुकी है। लेकिन मैं इसे यहां रख रहा हूं क्योंकि यह कुछ अन्य लोगों के लिए सहायक हो सकता है जो भविष्य में देखेंगे। इस समस्या को कम करने का सबसे अच्छा तरीका है x = x ++ और x = ++ x के लिए बनाए गए असेंबली कोड को देखना। कृपया थिंकिंगकैप का जवाब भी देखें।
नांतिमितव

मुझे पता है कि यह सुपर पुराना है, लेकिन मेरे पास एक सवाल है। क्या ऑपरेशन का उपरोक्त आदेश मानक द्वारा गारंटीकृत है? क्या यह संभव है कि वेतन वृद्धि से पहले असाइनमेंट निष्पादित किया जाता है?
एमरल्ड वेपन

@EmeraldWeapon यह जावा में परिभाषित किया गया है। यह केवल C / C ++ में है, क्या आप इस तरह के शेंनिगन्स को देखते हैं।
15

385
x = x++;

के बराबर है

int tmp = x;
x++;
x = tmp;

46
लोल, पुनरावर्ती परिभाषाओं के लिए याय। संभवतः आपको x=x+1x++
user606723

8
@ user606723: नहीं, मेरा मतलब पूरे बयान से था x = x++, केवल पोस्ट इंक्रीमेंट से नहीं x++
प्रिंस जॉन वेस्ले

20
मुझे नहीं लगता कि यह सब और स्पष्टीकरण के बिना उपयोगी है। उदाहरण के लिए, यह सच नहीं है, यह x = ++x;भी बराबर है int tmp = x; ++x; x = tmp;, इसलिए किस तर्क से हम यह घटा सकते हैं कि आपका उत्तर सही है (जो यह है)?
kvb 17

4
इससे भी अधिक स्पष्ट यह asm x=x++ =MOV x,tmp; INC x; MOV tmp,x
forker

3
@ फोर्कर: मुझे लगता है कि अगर आप असेंबली निर्देशों का उपयोग करते हैं तो यह स्पष्ट हो जाएगा जो कि प्रोसेसर माइकल पर लागू होता है;)
कार्ल

258

बयान:

x = x++;

के बराबर है:

tmp = x;   // ... this is capturing the value of "x++"
x = x + 1; // ... this is the effect of the increment operation in "x++" which
           //     happens after the value is captured.
x = tmp;   // ... this is the effect of assignment operation which is
           //     (unfortunately) clobbering the incremented value.

संक्षेप में, कथन का कोई प्रभाव नहीं है।

मुख्य बिंदु:

  • पोस्टफिक्स इन्क्रीमेंट / डीक्रीमेंट एक्सप्रेशन का मूल्य , इन्क्रिमेंट / डिक्रीमेंट होने से पहले ऑपरेंड का मूल्य है। (एक उपसर्ग रूप के मामले में, मूल्य ऑपरेशन के बाद ऑपरेंड का मूल्य है )

  • एक असाइनमेंट अभिव्यक्ति का आरएचएस पूरी तरह से मूल्यांकन किया जाता है (एलआरएचएस को सौंपा जाने से पहले किसी भी वेतन वृद्धि, वेतन वृद्धि और / या अन्य दुष्प्रभावों सहित) ।

ध्यान दें कि C और C ++ के विपरीत, जावा में एक अभिव्यक्ति के मूल्यांकन का क्रम पूरी तरह से निर्दिष्ट है और प्लेटफ़ॉर्म-विशिष्ट भिन्नता के लिए कोई जगह नहीं है। कंपाइलरों को केवल संचालन को फिर से चालू करने की अनुमति दी जाती है यदि यह वर्तमान थ्रेड के परिप्रेक्ष्य से कोड को निष्पादित करने का परिणाम नहीं बदलता है। इस मामले में, एक कंपाइलर को पूरे विवरण को अनुकूलित करने की अनुमति दी जाएगी क्योंकि यह साबित किया जा सकता है कि यह एक नो-ऑप है।


मामले में यह पहले से ही स्पष्ट नहीं है:

  • "x = x ++" किसी भी कार्यक्रम में लगभग एक गलती है।
  • ओपी (मूल प्रश्न के लिए!) का अर्थ शायद "x ++;" इसके बजाय "x = x ++;"।
  • एक ही चर पर ऑटो inc / decrement और असाइनमेंट को संयोजित करने वाले बयानों को समझना मुश्किल है, और इसलिए उनकी शुद्धता के बावजूद बचना चाहिए । इस तरह कोड लिखने की कोई आवश्यकता नहीं है।

उम्मीद है, FindBugs और PMD जैसे कोड चेकर्स कोड को इस तरह संदिग्ध मानेंगे।


7
एक साइड नोट के रूप में, ओपी, आप शायद के x++बजाय सिर्फ कहने का मतलब है x = x++
जॉन न्यूमूंस

3
सही है, लेकिन शायद जोर देते हैं कि वेतन वृद्धि होता है पद दाएँ हाथ अभिव्यक्ति मूल्यांकन, लेकिन पूर्व बाएं हाथ की ओर करने के लिए काम है, इसलिए स्पष्ट "अधिलेखित"
बोहेमियन

2
ऐसा लगता है कि उन हाई-स्कूल प्रोग्रामिंग ट्विस्टर्स में से एक है ... अपने बेसिक्स को क्लियर करने के लिए अच्छा है!
कुमारहर्ष

1
@Alberto - यह सुनना अच्छा है कि आप "विशेषज्ञ" बयानों को "सुसमाचार सच्चाई" के रूप में नहीं लेते हैं। हालांकि, जेएलएस से परामर्श करने के लिए मैंने जो कहा था, उसे मान्य करने का एक बेहतर तरीका। आपका संकलित / विघटित परीक्षण केवल यह बताता है कि मैंने जो कहा वह एक जावा संकलक के लिए मान्य है। अन्य (काल्पनिक रूप से) अलग व्यवहार कर सकते थे ... सिवाय इसके कि जेएलएस इसकी अनुमति नहीं देता है।
स्टीफन सी

4
बस एक FYI करें: यह मूल रूप से एक अलग प्रश्न पर पोस्ट किया गया था, जिसे इस एक के डुप्लिकेट के रूप में बंद कर दिया गया था और अब विलय कर दिया गया है।
शोग

33
int x = 7;
x = x++;

इसका C में अपरिभाषित व्यवहार है और जावा के लिए यह उत्तर देखें । यह कंपाइलर पर निर्भर करता है कि क्या होता है।


4
नहीं, यह आपके द्वारा उद्धृत उत्तर के अनुसार संकलक पर निर्भर नहीं करता है - कृपया संपादित करें - अभी के लिए -1
Mr_and_Mrs_D

@Mr_and_Mrs_D तब यह किस पर निर्भर करता है?
मैक

2
यह C_ के लिए अपरिभाषित व्यवहार_ है। यहां तक ​​कि यह कहना कि यह संकलक पर निर्भर है भ्रामक है - इसका मतलब है कि संकलक को इस व्यवहार को निर्दिष्ट करना चाहिए। मैं अपना वोट वापस करता हूं, लेकिन अपने उत्तर को संपादित करने पर विचार करें - संपादित करें: उफ़ मैं नहीं कर सकता - आपको इसे पहले संपादित करना होगा: D
Mr_and_Mrs_D

16

एक निर्माण जैसा x = x++;इंगित करता है कि आप शायद गलत समझ रहे हैं कि ++ऑपरेटर क्या करता है:

// original code
int x = 7;
x = x++;

++ऑपरेटर को हटाने के आधार पर, समान कार्य करने के लिए इसे फिर से लिखते हैं :

// behaves the same as the original code
int x = 7;
int tmp = x; // value of tmp here is 7
x = x + 1; // x temporarily equals 8 (this is the evaluation of ++)
x = tmp; // oops! we overwrote y with 7

अब, इसे करने के लिए फिर से लिखना (मुझे क्या लगता है) आप चाहते थे:

// original code
int x = 7;
x++;

यहां सूक्ष्मता यह है कि ++ऑपरेटर एक अभिव्यक्ति के विपरीत चर को संशोधित करता हैx , जैसे कि x + xएक इंट वैल्यू का मूल्यांकन करना लेकिन चर xको अपरिवर्तित छोड़ देना । आदरणीय forपाश की तरह एक निर्माण पर विचार करें :

for(int i = 0; i < 10; i++)
{
    System.out.println(i);
}

i++वहाँ नोटिस ? यह एक ही ऑपरेटर है। हम इस forलूप को इस तरह से फिर से लिख सकते हैं और यह समान व्यवहार करेगा:

for(int i = 0; i < 10; i = i + 1)
{
    System.out.println(i);
}

मैं ++ज्यादातर मामलों में बड़े अभिव्यक्तियों में ऑपरेटर का उपयोग करने के खिलाफ भी सलाह देता हूं । की सूक्ष्मता की वजह से जब यह पूर्व की तुलना में बाद के वेतन वृद्धि (में मूल चर को संशोधित करता है ++xऔर x++, क्रमशः), यह बहुत आसान सूक्ष्म कीड़े कि नीचे ट्रैक करने के लिए मुश्किल हो जाता है शुरू करने की है।


13

बाइट कोड के अनुसारवर्ग फ़ाइलों से प्राप्त ,

दोनों असाइनमेंट एक्स को बढ़ाते हैं, लेकिन अंतर का समय है when the value is pushed onto the stack

में Case1 , पुश वेतन वृद्धि से पहले होता है (और फिर बाद में सौंपा) (अनिवार्य रूप से अपने वेतन वृद्धि अर्थ कुछ नहीं करता है)

में Case2 , वृद्धि पहले होती है (इसे 8 बनाते हुए) और फिर स्टैक पर धकेल दिया जाता है (और फिर x को सौंपा जाता है)

मामला एक:

int x=7;
x=x++;

बाइट कोड:

0  bipush 7     //Push 7 onto  stack
2  istore_1 [x] //Pop  7 and store in x
3  iload_1  [x] //Push 7 onto stack
4  iinc 1 1 [x] //Increment x by 1 (x=8)
7  istore_1 [x] //Pop 7 and store in x
8  return       //x now has 7

केस 2:

int x=7; 
x=++x;

बाइट कोड

0  bipush 7     //Push 7 onto stack
2  istore_1 [x] //Pop 7 and store in x
3  iinc 1 1 [x] //Increment x by 1 (x=8)
6  iload_1  [x] //Push x onto stack
7  istore_1 [x] //Pop 8 and store in x
8  return       //x now has 8
  • यहां स्टैक का संदर्भ ओपरेट स्टैक से है, स्थानीय: x इंडेक्स: 1 प्रकार: इंट

क्या आप कृपया विवरण में अपना उत्तर बता सकते हैं।
निहार

Pls संदर्भित लिंक और टिप्पणियों पर एक नज़र डालें
शाम


8

पोस्ट इंक्रीमेंट ऑपरेटर निम्नानुसार काम करता है:

  1. ऑपरेंड के पिछले मूल्य को स्टोर करें।
  2. ऑपरेंड के मूल्य में वृद्धि।
  3. ऑपरेंड का पिछला मान लौटाएं।

अतः कथन

int x = 7;
x = x++; 

निम्नानुसार मूल्यांकन किया जाएगा:

  1. x का मूल्य 7 से आरंभ किया गया है
  2. वेतन वृद्धि ऑपरेटर एक्स के पिछले मूल्य यानी 7 को वापस करने के लिए संग्रहीत करता है।
  3. एक्स को बढ़ाता है, इसलिए अब एक्स 8 है
  4. X के पिछले मान को लौटाता है यानी 7 और इसे x को वापस सौंपा जाता है, इसलिए x फिर से 7 हो जाता है

तो x वास्तव में बढ़ा हुआ है, लेकिन चूंकि x ++ परिणाम को वापस x पर नियत कर रहा है, इसलिए x का मान उसके पिछले मान से अधिक है।


लेकिन msvc x में 8. है। जीसीसी और क्लैंग x में हां 7. है
ग्रीष्मकालीन सूर्य

7

वृद्धि को x कहा जाता है के बाद होता है, इसलिए x अभी भी बराबर होता है। x कहा जाता है जब x 8 के बराबर होगा


7

जब आप xइसके लिए मान फिर से असाइन करते हैं तब भी 7. प्रयास करें x = ++xऔर आपको 8 और काम मिलेंगे

x++; // don't re-assign, just increment
System.out.println(x); // prints 8

6

क्योंकि x ++ वैरिएबल पर असाइन होने वाले AFTER के मान को बढ़ाता है। इस लाइन के निष्पादन के दौरान और इसके बाद:

x++;

varialbe x में अभी भी मूल मान (7) होगा, लेकिन x को फिर से किसी अन्य लाइन पर उपयोग करना, जैसे कि

System.out.println(x + "");

आपको 8 देंगे।

यदि आप अपने असाइनमेंट स्टेटमेंट पर x का एक बढ़े हुए मूल्य का उपयोग करना चाहते हैं, तो उपयोग करें

++x;

यह x को 1 से बढ़ाता है, फिर उस मान को चर x पर असाइन करता है।

[संपादित करें] x = x ++ के बजाय, यह सिर्फ x ++ है; पूर्व अपने आप में x का मूल मान बताता है, इसलिए यह वास्तव में उस रेखा पर कुछ भी नहीं करता है।


जो कहता है कि यह असाइन करने के बाद वेतन वृद्धि करता है, और जो कहता है कि यह 8 प्रिंट करेगा। यह असाइन करने से पहले वेतन वृद्धि करता है, और यह 7. प्रिंट करता है।
आर। मार्टिनो फर्नांडीस

यदि x मूल रूप से 7 है, System.out.println (String.valueOf (x ++)); प्रिंट 7. आपको यकीन है कि हम उसी प्रोग्रामिंग भाषा के बारे में बात कर रहे हैं?
जॉसफस

हां मैं हूं। यह ideone.com/kj2UU इस उत्तर के दावों की तरह 8 प्रिंट नहीं करता है।
आर। मार्टिनो फर्नांडिस

हां, मैं गलत था। x = x ++ x बढ़ाने से पहले 7 से x पहले असाइन करेगा। जैसा कि x ++ (जो अपने आप में एक असाइनमेंट है) पहले x = (जो भी) होता है, उससे पहले x = = (जो भी) में x को असाइन किया गया मान होगा। क्षमा करें, मैंने ऐसा नहीं देखा।
जोसेफस

1
दरअसल, वेतन वृद्धि पहली बात है। ideone.com/xOIDU
आर। मार्टिनो फर्नांडीस

4

क्या होता है जब int x = 7; x = x++;?

ans -> का x++अर्थ है एक्सप्रेशन के लिए पहले x का मान और फिर इसे 1 से बढ़ाना।
यही आपके मामले में होता है। RHS पर x का मान LHS पर परिवर्तनशील x पर कॉपी किया जाता है और फिर x1 से मान बढ़ाया जाता है।

इसी प्रकार ++x साधन ->एक के बाद पहली बार एक्स के मूल्य में वृद्धि और फिर अभिव्यक्ति में उपयोग करें।
तो आपके मामले में यदि आप करते x = ++x ; // where x = 7
हैं तो आपको 8 का मूल्य मिलेगा।

अधिक स्पष्टता के लिए यह पता लगाने की कोशिश करें कि निम्नलिखित कोड में कितने प्रिंटफ स्टेटमेंट निष्पादित होंगे

while(i++ <5)   
  printf("%d" , ++i);   // This might clear your concept upto  great extend

सही नहीं है "RHS पर x का मान LHS पर चर x में कॉपी किया जाता है और फिर x का मान 1 से बढ़ जाता है" - यह x8 हो जाएगा, लेकिन यह 7 है - वेतन वृद्धि पढ़ने और असाइनमेंट के बीच होती है
user85421

3

++xप्री-इन्क्रीमेंट ->x का उपयोग होने से पहले बढ़ा हुआ
x++है, पोस्ट-इन्क्रीमेंट ->x का उपयोग होने के बाद बढ़ा हुआ है

int x = 7; -> x get 7 value <br>
x = x++; -> x get x value AND only then x is incremented

1

तो इसका मतलब है: के x++बराबर नहीं हैx = x+1

इसलिये:

int x = 7; x = x++;
x is 7

int x = 7; x = x = x+1;
x is 8

और अब यह थोड़ा अजीब लगता है:

int x = 7; x = x+=1;
x is 8

बहुत संकलक निर्भर!


2
किसने कहा कि यह पहली जगह में बराबर था?
फोरट्रान

1
अगर मैं होता तो मैं इन किताबों को तुरंत एक्सडी कर देता। किसी भी स्थिति में, यह (x = x + 1, x-1)सी की तरह होता , जहाँ अल्पविराम द्वारा अलग किए गए अभिव्यक्ति की अनुमति होती है।
फोरट्रान

3
@fortran: पृष्ठ 159 पर "द जावा प्रोग्रामिंग लैंग्वेज, थर्ड एडिशन" की मेरी पुरानी-पुरानी कॉपी में लिखा है कि "" अभिव्यक्ति i ++ i = i + 1 के बराबर है, सिवाय इसके कि मेरा केवल एक बार मूल्यांकन किया जाए। '' किसने कहा। पहली जगह में; जेम्स गोस्लिंग, यह दिखाई देगा। जावा कल्पना के इस संस्करण का यह हिस्सा असाधारण रूप से अस्पष्ट और खराब निर्दिष्ट है; मुझे लगता है कि बाद में संस्करणों ने वास्तविक ऑपरेटर शब्दार्थ को स्पष्ट रूप से व्यक्त करने के लिए भाषा को साफ कर दिया।
एरिक लिपर्ट

2
@fortran: "सिवाय I द्वारा केवल एक बार मूल्यांकन किया जाता है" मानक यह बताने का प्रयास कर रहा है कि एक अभिव्यक्ति "M ()। x ++" केवल एक बार M () कहती है। एक कम अस्पष्ट और अधिक सटीक शब्दांकन इस बात पर जोर देगा कि इसके भंडारण स्थान का निर्धारण करने के लिए एक चर के रूप में मूल्यांकन करने के बीच अंतर है - जिसका अर्थ है "केवल एक बार" यहां मूल्यांकन किया गया है - और उस भंडारण स्थान पर पढ़ना या लिखना - - दोनों में से कोई भी 'मूल्यांकन' की एक उचित लेकिन गलत व्याख्या हो सकती है। स्पष्ट रूप से भंडारण स्थान को पढ़ा और लिखा दोनों होना चाहिए!
एरिक लिपर्ट

1
"बहुत संकलक निर्भर" - बिल्कुल नहीं!
स्टीफन सी

-1

x = x ++;

यह पोस्ट-इन्क्रीमेंट ऑपरेटर है। इसे "ऑपरेटर के मूल्य का उपयोग करें और फिर ऑपरेंड में वृद्धि" के रूप में समझा जाना चाहिए।

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

x = ++ x;

यह ऑपरेटर पहले x के मान को 1 से बढ़ाता है और उसके बाद वापस x पर मान देता है।


-1

मुझे लगता है कि इस विवाद को कोड में जाने और सिर्फ सोच के बिना हल किया जा सकता है।

कार्य के रूप में i ++ और ++ पर विचार करें, Func1 और Func2 कहें।

अब मैं = 7;
Func1 (i ++) 7 रिटर्न, Func2 (++ i) रिटर्न 8 (हर कोई यह जानता है)। आंतरिक रूप से दोनों कार्य I से 8 तक बढ़ते हैं, लेकिन वे विभिन्न मान लौटाते हैं।

इसलिए मैं = i ++ फ़ंक्शन को कॉल करता है Func1। फ़ंक्शन के अंदर मैं 8 में वृद्धि करता हूं, लेकिन फ़ंक्शन पूरा होने पर 7 लौटता है।

तो अंततः 7 को मुझे आवंटित किया जाता है। (इसलिए अंत में, मैं = 7)


2
यहां कोई वैध "विवाद" नहीं है। कोड demonstrably एक विशेष तरीके से व्यवहार करता है, और व्यवहार JLS के अनुरूप होता है। जो कोई भी यह सोचता है कि यह अलग तरह से व्यवहार करता है या तो उसने कोशिश नहीं की है, या वे बहक गए हैं। (यह कहना थोड़ा सा है कि 7 x 7 49 है "विवादास्पद" जब कोई अपने समय सारणी को भूल जाता है ...)
स्टीफन C

-2

ऐसा इसलिए है क्योंकि आपने पोस्ट-इन्क्रीमेंट ऑपरेटर का उपयोग किया है। इस कोड की निम्नलिखित पंक्ति में

x = x++;

क्या होता है, आप x से x का मान बता रहे हैं। x का मान x को दिए जाने के बाद x + इंक्रीमेंट x। इसी तरह से पोस्ट-इन्क्रीमेंट ऑपरेटर काम करते हैं। वे एक बयान के निष्पादित होने के बाद काम करते हैं। तो आपके कोड में, x को पहले लौटाया जाता है, उसके बाद इसे बढ़ा दिया जाता है।

अगर तुमने किया

x = ++x;

उत्तर 8 होगा क्योंकि आपने पूर्व-वेतन वृद्धि ऑपरेटर का उपयोग किया था। यह x का मान वापस करने से पहले पहले मूल्य बढ़ाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.