Bu neden sonsuz bir döngüye giriyor?


493

Takip koduna sahibim:

public class Tests {
    public static void main(String[] args) throws Exception {
        int x = 0;
        while(x<3) {
            x = x++;
            System.out.println(x);
        }
    }
}

Sadece yazması gerektiğini biliyoruz x++ya da x=x+1üzerinde x = x++önce xkendine atfedilmeli ve daha sonra artırılmalıdır. Neden değer olarak xdevam ediyor 0?

--Güncelleme

İşte bayt kodu:

public class Tests extends java.lang.Object{
public Tests();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[])   throws java.lang.Exception;
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   iconst_3
   4:   if_icmpge   22
   7:   iload_1
   8:   iinc    1, 1
   11:  istore_1
   12:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   15:  iload_1
   16:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
   19:  goto    2
   22:  return

}

Anlamaya çalışmak için talimatları okuyacağım ...


8
Olanlardan şüphe duyuyorum: 1. bir kayda x yükleyin (= 0); 2. x (x = 1) artış; 3. Kayıt değerini x (x = 0) içine kaydedin. C / C ++ 'da bu tanımsız bir davranış olacaktır, çünkü 2 ve 3'ün sırasını tanımlayacak resmi bir sıra noktası yoktur. Umarım birisi size Java spesifikasyonundan eşdeğer bir şey teklif edebilir.
Rup

19
Ne olacağını görmek için bunu C ++ 'da denedik ve 1,2,3 yazdırır ve çıkar. Bu kadarını beklemiyordum. Tanımsız davranış olduğu için derleyiciye bağımlı olduğunu varsayıyorum. Biz gnu g ++ kullandık.
yas

13
@ saj x++artım sonrasıdır ; sonucunx= atanmasıdır ; Sonuç ait orijinal (ve artım bir yan etkisi yoktur, ama bu sonuç değişmez) bu şekilde yorumlanabilir Yani,x++xvar tmp = x; x++; x = tmp;
Marc Gravell

5
Şimdi pişman olduğum popüler bir sorum var, doğru cevap seçildikten sonra bile (tekrarlanan) cevaplar gelmeyi bırakmıyor. "Son Etkinlik" ekranım aynı cevaplarla dolu ve daha fazlası ...
Tom Brito

3
@Rob Vermeulen yorum yapmadan önce tüm soruyu okumak isteyebilirsiniz ..;) Bu benim bir öğrencim tarafından yapılan bir koddu ve bu davranışın nedenini merak ettim.
Tom Brito

Yanıtlar:


354

Not : Aslında, C # kodunu örnekleme amacıyla bu cevapta yayınladım, çünkü C # intparametreleri refanahtar kelimeyle referans olarak geçirmenize izin veriyor . MutableIntGoogle'da bulduğum birinci sınıfı kullanarak gerçek yasal Java koduyla güncellemeye karar verdim ref. Bunun cevaba yardım edip etmediğini gerçekten söyleyemem. Ben şahsen bu kadar çok Java geliştirmesi yapmadığımı söyleyeceğim; bu yüzden bildiğim kadarıyla bu noktayı açıklamanın çok daha deyimsel yolları olabilir.


Belki de bunu yapan şeyin eşdeğerini yapmak için bir yöntem yazarsak x++, bunu daha net hale getirir.

public MutableInt postIncrement(MutableInt x) {
    int valueBeforeIncrement = x.intValue();
    x.add(1);
    return new MutableInt(valueBeforeIncrement);
}

Sağ? Geçirilen değeri artırın ve orijinal değeri döndürün: bu, arttırma operatörünün tanımıdır.

Şimdi bu davranışın örnek kodunuzda nasıl oynandığını görelim:

MutableInt x = new MutableInt();
x = postIncrement(x);

postIncrement(x)ne yapar? Artışlar x, evet. Ve sonra neler döndürür x oldu sayının önceki . Bu dönüş değeri daha sonra atandı x.

Böylece, atanan değerlerin sırası x0, sonra 1, sonra 0 olur.

Yukarıdakileri yeniden yazarsak, bu daha net olabilir:

MutableInt x = new MutableInt();    // x is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
x = temp;                           // Now x is 0 again.

Aslında üzerinde sabitleme değiştirdiğinizde, o xyukarıda atama sol tarafında y, "Eğer ilk artışlarla x olduğunu görebilir ve daha sonra y de ilişkilendirir" karıştırılmamalıdır olarak beni oldukça etkiliyor. xAtanan bu değildir y; öyle eskiden atanan değerx . Gerçekten, enjekte yetmek işleri yukarıdaki senaryodan farklı kılmaz ; basitçe:

MutableInt x = new MutableInt();    // x is 0.
MutableInt y = new MutableInt();    // y is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
y = temp;                           // y is still 0.

Bu yüzden açık: x = x++x'in değerini etkili bir şekilde değiştirmez. Her zaman x'in x 0 , sonra x 0 + 1 ve tekrar x 0 değerlerine sahip olmasına neden olur .


Güncelleme : Bu arada, xarttırma işlemi ve yukarıdaki örnekte atama arasında 1 "e atanmış olduğundan şüphe ederseniz , bu ara değerin gerçekten" var "olduğunu göstermek için hızlı bir demo attım. yürütme iş parçacığında asla "görülmez".

x = x++;Ayrı bir iş parçacığı sürekli xolarak konsola değerini yazdırırken demo bir döngü içinde çağırır .

public class Main {
    public static volatile int x = 0;

    public static void main(String[] args) {
        LoopingThread t = new LoopingThread();
        System.out.println("Starting background thread...");
        t.start();

        while (true) {
            x = x++;
        }
    }
}

class LoopingThread extends Thread {
    public @Override void run() {
        while (true) {
            System.out.println(Main.x);
        }
    }
}

Aşağıda, yukarıdaki programın çıktısından bir alıntı yer almaktadır. Hem 1s hem de 0s'ın düzensiz oluşumuna dikkat edin.

Arka plan iş parçacığı başlatılıyor ...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1

1
Java'da referans ile geçmek için bir sınıf oluşturmanız gerekmez (bu kesinlikle işe yarayacaktır). IntegerStandart kütüphanenin bir parçası olan sınıfı kullanabilirsiniz ve hatta int neredeyse şeffaf bir şekilde otomatik olarak kutudan çıkarılma ve hatta şeffaflıktan yararlanma avantajına sahiptir .
rmeador

3
@rmeador Integer değişmez, bu yüzden değerini değiştiremediniz. Ancak AtomicInteger değiştirilebilir.
ILMTitan

5
@Dan: Bu arada, xson örneğinizde bildirilmelidir volatile, aksi takdirde tanımsız bir davranıştır ve 1s'nin uygulamaya özel olduğunu görmek .
axtavt

4
@burkestar: Bu bir Java sorusu ve (yanlış olmadıkça) davranış C ++ 'da tanımsız olduğundan, bu durumda bu bağlantının oldukça uygun olduğunu düşünmüyorum .
Dan Tao

5
@Tom Brito - C'de tanımlanmadı ... ++ olabilir önce veya sonra atama yapılması. Pratik olarak, Java ile aynı şeyi yapan bir derleyici olabilir, ancak bahse girmek istemezsiniz.
detly

170

x = x++ aşağıdaki şekilde çalışır:

  • İlk olarak ifadeyi değerlendirir x++. Bu ifadenin değerlendirilmesi, bir ifade değeri (artıştan önceki değerdir x) ve artışlar üretir x.
  • Daha sonra xartan değerin üzerine yazarak ifade değerini atar .

Yani, olaylar dizisi aşağıdaki gibi görünüyor ( javap -cyorumlarım tarafından üretilen gerçek bir ayrıştırılmış bayt kodu ):

   8: iload_1 // Yığında mevcut x değerini hatırla
   9: iinc 1, 1 // Artış x (yığını değiştirmez)
   12: istore_1 // Yığından x'e yeniden yazılmış değer yazın

Karşılaştırma için x = ++x:

   8: iinc 1, 1 // Artış x
   11: iload_1 // x'in değerini yığına it
   12: istore_1 // Yığından x değerine pop değeri

bir test yaparsanız, testin önce arttığını ve daha sonra nitelikleri görebilirsiniz. Bu yüzden sıfır atfetmemelidir.
Tom Brito

2
@Tom asıl mesele bu - çünkü bunların hepsi tek bir sekans, belli olmayan (ve muhtemelen tanımsız) bir şekilde işler yapıyor. Bunu test etmeye çalışarak bir dizi noktası ekleyip farklı davranışlar elde edersiniz.
Rup

Bayt kodu çıktınızla ilgili olarak: iincbir değişkeni artırdığına, bir yığın değerini artırdığına veya yığın üzerinde bir değer bırakmadığına dikkat edin (neredeyse diğer tüm aritmetik işlemlerin aksine). ++xKarşılaştırma için oluşturulan kodu eklemek isteyebilirsiniz .
Anon

3
@Rep C veya C ++ ile tanımlanmamış olabilir, ancak Java'da iyi tanımlanmıştır.
ILMTitan


104

Bunun nedeni, değerinin xhiç artmamasıdır.

x = x++;

eşittir

int temp = x;
x++;
x = temp;

Açıklama:

Bu işlem için bayt koduna bakalım. Bir örnek sınıf düşünün:

class test {
    public static void main(String[] args) {
        int i=0;
        i=i++;
    }
}

Şimdi bunun için sınıf sökücüyü çalıştırıyoruz:

$ javap -c test
Compiled from "test.java"
class test extends java.lang.Object{
test();
  Code:
   0:    aload_0
   1:    invokespecial    #1; //Method java/lang/Object."<init>":()V
   4:    return

public static void main(java.lang.String[]);
  Code:
   0:    iconst_0
   1:    istore_1
   2:    iload_1
   3:    iinc    1, 1
   6:    istore_1
   7:    return
}

Şimdi Java VM yığın tabanlı, yani her işlem için veriler yığına itilecek ve yığından, veriler işlemi gerçekleştirmek için çıkacaktır. Başka bir veri yapısı da vardır, tipik olarak yerel değişkenleri saklamak için bir dizi. Yerel değişkenlere sadece dizinin dizinleri olan kimlikler verilir.

Bize bakalım mnemonic'ler içinde main()yöntemle:

  • iconst_0: Sabit değer 0 yığına iletilir.
  • istore_1: Yığının üst elemanı üzerinden attı ve indeksi ile yerel değişken saklanır 1
    olup x.
  • iload_1: Konumda değeri 1değeri x olan bir 0yığın içine itilir.
  • iinc 1, 1: Bellek konumundaki 1değer artar 1. Böylece xşimdi olur 1.
  • istore_1: Yığının üst kısmındaki değer bellek konumuna kaydedilir 1. Bu, artan değerinin üzerine yazmak0 için atanır .x

Böylece değeri xdeğişmez sonsuz döngüye neden olur.


5
Aslında artmaktadır (anlamı budur ++), ancak daha sonra değişkenin üzerine yazılır.
Progman

10
int temp = x; x = x + 1; x = temp;örneğin bir totoloji kullanmamak daha iyidir.
Scott Chamberlain

52
  1. Önek notasyonu, ifade değerlendirilmeden ÖNCE değişkeni artıracaktır.
  2. Postfix gösterimi, ifade değerlendirmesinden SONRA artacaktır.

Ancak " =" operatörün önceliği " ++" ' den daha düşüktür .

Bu yüzden x=x++;aşağıdaki gibi değerlendirmelisiniz

  1. x ödev için hazırlandı (değerlendirildi)
  2. x artırılır
  3. Öğesine xatanan önceki değer x.

Bu en iyi cevap. Bazı işaretlemeler biraz daha öne çıkmasına yardımcı olabilirdi.
Justin Force

1
Bu yanlış. Bu öncelikle ilgili değil. C ve C ++ ' ++dan daha yüksek önceliğe sahiptir =, ancak ifade bu dillerde tanımsızdır.
Matthew Flaschen

2
Orijinal soru Java hakkındadır
Jaydee

34

Cevapların hiçbiri oldukça yerinde değil, işte burada:

Yazarken int x = x++, xyeni değerde olmak için atamazsınız x, x++ifadenin dönüş değeri olarak atarsınız. Bu x, Colin Cochrane'nin cevabında ima edildiği gibi , orijinal değeri olur .

Eğlenmek için aşağıdaki kodu test edin:

public class Autoincrement {
        public static void main(String[] args) {
                int x = 0;
                System.out.println(x++);
                System.out.println(x);
        }
}

Sonuç

0
1

İfadenin dönüş değeri x, sıfır olan başlangıç ​​değeridir . Ama daha sonra, değerini okurken x, güncellenmiş değeri alırız, yani.


Bayt kodu satırlarını anlamaya çalışacağım, güncellememi görün, bu yüzden açık olacak .. :)
Tom Brito

Println () kullanmak bunu anlamakta bana çok yardımcı oldu.
ErikE


18

Bu açıklama:

x = x++;

şöyle değerlendirir:

  1. it xYığının üzerine ;
  2. Artış x;
  3. xYığından pop .

Böylece değer değişmez. Bunu şununla karşılaştırın:

x = ++x;

aşağıdaki gibi değerlendirir:

  1. Artış x;
  2. xYığının üzerine itin ;
  3. xYığından pop .

Ne istiyorsun:

while (x < 3) {
  x++;
  System.out.println(x);
}

13
Kesinlikle doğru uygulama, ama soru 'neden?'.
p.campbell

1
Orijinal kod x üzerinde artım sonrası kullanıyordu ve sonra bunu x'e ataıyordu. x, artıştan önce x'e bağlı olacaktır, bu nedenle değerleri asla değiştirmeyecektir.
wkl

5
@cletus Ben downvoter değilim, ama ilk cevabınız açıklama içermiyordu. Sadece 'x ++ `dedi.
Petar Minchev

4
@cletus: Ben inmedim, ama cevabın aslında sadece x++kod snippet'iydi.
p.campbell

10
Açıklama da yanlış. Kod önce x'e x atandıktan sonra x değerini arttırırsa, düzgün çalışır. Sadece x++;çözümünüzü değiştirin x=x; x++;ve orijinal kodun yaptığını iddia ettiğiniz şeyi yapın.
Eylül'de Wooble

10

Cevap oldukça basittir. İşlerin değerlendirilme sırası ile ilgilidir. x++değeri döndürür, xsonra artırır x.

Sonuç olarak, ifadenin değeri x++olur 0. Yani x=0döngüdeki her seferinde ataıyorsunuz. Kesinlikle x++bu değeri arttırır , ancak bu atamadan önce olur.


1
Vay be, cevap kısa ve basit olduğunda bu sayfada çok fazla ayrıntı var, yani bu.
Charles Goodwin

8

Gönderen http://download.oracle.com/javase/tutorial/java/nutsandbolts/op1.html

Artış / eksiltme işleçleri, işlenenden önce (önek) veya sonra (postfix) uygulanabilir. Kod sonucu ++; ve ++ sonuç; her ikisi de sonuç olarak bir artırılır. Tek fark, önek sürümünün (++ sonuç) artan değere, son düzeltme sürümünün (sonuç ++) ise orijinal değere göre değerlendirilmesidir . Sadece basit bir artış / azaltma yapıyorsanız, hangi sürümü seçtiğinizin bir önemi yoktur. Ancak bu operatörü daha büyük bir ifadenin parçası olarak kullanırsanız, seçtiğiniz operatör önemli bir fark yaratabilir.

Örneklemek için aşağıdakileri deneyin:

    int x = 0;
    int y = 0;
    y = x++;
    System.out.println(x);
    System.out.println(y);

Hangi 1 ve 0 yazdıracak.


1
Sorun değerlendirme sonucu değil, mağazaların sırası.
Rup

2
Katılmıyorum. X = 0 ise x ++ 0 döndürür. Bu nedenle x = x ++ x = 0 ile sonuçlanır.
Colin Cochrane

Rup bu konuda haklı. Bu özel durumda söz konusu olan mağazaların sırası. y = x ++, x = x ++ ile aynı değildir; Sonuncusunda, x'e aynı ifadede 2 değer atanır. Sol el x, 0 olan x ++ ifadesinin değerlendirilmesinin sonucu olarak atanmaktadır. Sağ taraf x 1'e artırılmaktadır. Hangi sırayla bu 2 atamanın gerçekleştiği sorundur. Önceki yazılardan, bunun çalışma şeklinin olduğu açıktır: eval = x ++ => eval == 0: artış sağ x => x == 1: sol x = eval => x == 0
Michael Ekoka

7

Aşağıdaki davranışı etkili bir şekilde elde edersiniz.

  1. x değerini (0 olan) sağ tarafın "sonucu" olarak al
  2. x değerini arttırır (böylece x şimdi 1'dir)
  3. sağ tarafın sonucunu (0 olarak kaydedildi) x'e (x şimdi 0'dır) atayın

Fikir, artım sonrası operatörünün (x ++) söz konusu değişkeni, kullanıldığı denklemde kullanım için değerini döndürdükten SONRA arttırır.

Düzenleme: Yorum nedeniyle biraz ekleme. Aşağıdaki gibi düşünün.

x = 1;        // x == 1
x = x++ * 5;
              // First, the right hand side of the equation is evaluated.
  ==>  x = 1 * 5;    
              // x == 2 at this point, as it "gave" the equation its value of 1
              // and then gets incremented by 1 to 2.
  ==>  x = 5;
              // And then that RightHandSide value is assigned to 
              // the LeftHandSide variable, leaving x with the value of 5.

Tamam, ancak 2. ve 3. adımların sırasını ne belirler?
Rup

@Rup - Dil onu tanımlar. Önce denklemin sağ tarafı değerlendirilir (bu durumda "x ++") ve sonuç sol taraftaki değişkene atanır. Dil böyle çalışır. Denklem için "x ++" "döndüren" x kadarıyla, postfix artış operatörü bu şekilde çalışır (x değerini döndürür, sonra artırır). "--X" olsaydı, o zaman olurdu (x değerini artır, sonra değeri döndür). Dönüş burada doğru kelime değil, ama fikri anladınız.
RHSeeger

7

Neler olduğunu anlamak için makine koduna gerçekten ihtiyacınız yok.

Tanımlara göre:

  1. Atama operatörü, sağ taraftaki ifadeyi değerlendirir ve bunu geçici bir değişkende saklar.

    1.1. Mevcut x değeri bu geçici değişkene kopyalanır

    1.2. x şimdi artırıldı.

  2. Geçici değişken daha sonra ifadenin sol tarafına kopyalanır, bu x şans eseri! Bu yüzden x'in eski değeri tekrar kendi içine kopyalanır.

Oldukça basit.


5

Çünkü bu durumda asla artmaz. x++bu durumda olduğu gibi artırılmadan önce değerini kullanacaktır:

x = 0;

Ancak bunu yaparsanız ++x;bu artacaktır.


bir test yaparsanız, testin önce arttığını ve daha sonra nitelikleri görebilirsiniz. Bu yüzden sıfır atfetmemelidir.
Tom Brito

1
@Tom: cevabımı gör - Bir testte x ++ 'ın x'in eski değerini döndürdüğünü gösterdim. Burası kırılıyor.
Robert Munteanu

"bir test yaparsanız" - bazı insanlar C ile yazılmış bir testin bize Java'nın ne yapacağını, C'nin ne yapacağını bile söylemeyeceğini söylediğini düşünüyor.
Jim Balter

3

Değeri 0 olduğu için değer x++0'da kalır. Bu durumda, değerinin xartırılıp artırılmaması önemli değildir, ödev x=0yürütülür. Bu geçici olarak artan değerin üzerine yazacaktır x("çok kısa bir süre için 1").


Ancak x ++ bir gönderim işlemidir. Bu nedenle atama tamamlandıktan sonra x artırılmalıdır.
Sagar V

1
@Sagar V: sadece ifade için x++ için, tüm ödev için değilx=x++;
Progman

Hayır, sadece ödevde kullanılacak x değerinin okunmasından sonra artırılması gerektiğini düşünüyorum.
Rup

1

Bu, diğerinden nasıl beklediğinizle çalışır. Önek ve postfix arasındaki farktır.

int x = 0; 
while (x < 3)    x = (++x);

1

X ++ 'ı, X'in ne olduğunu "döndüren" bir işlev çağrısı olarak düşünün önce (bu nedenle buna artım sonrası denir).

Yani işlem sırası:
1: arttırmadan önce x değerini önbelleğe al
2: artış x
3: önbelleğe alınan değeri döndürür (artmadan önce x)
4: dönüş değeri x'e atanır


Tamam, ancak 3. ve 4. adımların sırasını ne belirler?
Rup

"X artıştan önce ne olduğunu döndürür" yanlış, güncellememe bakın
Tom Brito

Gerçekte adım 3 ve 4 ayrı işlemler değildir - gerçekten bir değer döndüren bir işlev çağrısı değildir , sadece bu şekilde düşünmeye yardımcı olur. Ne zaman bir göreviniz varsa, sağ taraf "değerlendirilir", sonuç sol tarafa atanır, değerlendirme sonucu, işlem sırasını anlamanıza yardımcı olduğu için bir dönüş değeri olarak düşünülebilir, ancak gerçekte .
jhabbott

Hata! Adım 2 ve 4'ü kastettim - döndürülen değer neden artan değerin üstünde saklanıyor?
Rup

1
Bu, bir atama işlemi tanımının bir parçasıdır, önce sağ taraf tamamen değerlendirilir, daha sonra sonuç sol tarafa atanır.
jhabbott

1

++ rhs üzerindeyken, sayı artırılmadan önce sonuç döndürülür. ++ x olarak değiştirin ve iyi olurdu. Java bunu artım yerine tek bir işlem (x'den x'e atama) gerçekleştirmek üzere optimize ederdi.


1

Gördüğüm kadarıyla, hata, artan değeri geçersiz kılma ataması nedeniyle, artıştan önceki değerle oluşur, yani artışı geri alır.

Özellikle, "x ++" ifadesi, artımdan sonra "x" değerine sahip olan "++ x" yerine, artıştan önce "x" değerine sahiptir.

Bayt kodunu araştırmakla ilgileniyorsanız, söz konusu üç satıra bir göz atacağız:

 7:   iload_1
 8:   iinc    1, 1
11:  istore_1

7: iload_1 # 2. yerel değişkenin değerini yığına
koyacaktır 8: iinc 1,1 #, 2. yerel değişkeni 1 ile artıracaktır, yığına dokunulmadan bırakıldığını unutmayın!
9: yığının tepesine pop ve 2 yerel değişkene bu öğesinin değerini kurtaracak istore_1 #
(Her JVM talimat etkilerini okuyabilir burada )

Bu nedenle yukarıdaki kod süresiz döngü halindeyken, ++ x ile sürüm değişmez. ++ x için bayt kodu bir yıl önce yazdığım 1.3 Java derleyicisinden hatırladığım kadarıyla oldukça farklı görünmeli, bayt kodu şu şekilde olmalı:

iinc 1,1
iload_1
istore_1

Bu nedenle, sadece ilk iki satırı değiştirmek, anlambilimi, artışın ardından yığının üstünde kalan değer (yani ifadenin 'değeri') artımdan sonraki değer olacak şekilde değiştirir.


1
    x++
=: (x = x + 1) - 1

Yani:

   x = x++;
=> x = ((x = x + 1) - 1)
=> x = ((x + 1) - 1)
=> x = x; // Doesn't modify x!

Buna karşılık

   ++x
=: x = x + 1

Yani:

   x = ++x;
=> x = (x = x + 1)
=> x = x + 1; // Increments x

Tabii ki sonuç, adil x++;ya da ++x;kendi başına bir çizgide aynıdır .


0
 x = x++; (increment is overriden by = )

çünkü yukarıdaki ifade x asla 3'e ulaşmaz;


0

Java spesifikasyonunda bunun davranışını tam olarak tanımlayan bir şey olup olmadığını merak ediyorum. (Açıkçası bu ifadenin anlamı kontrol edemeyecek kadar tembel olduğumdur.)

Tom'un bayt kodundan not edin, anahtar satırlar 7, 8 ve 11'dir. Satır 7, hesaplama yığınına x yükler. Satır 8 artışları x. Satır 11, yığındaki değeri x'e geri kaydeder. Değerleri kendilerine geri atamadığınız normal durumlarda, yükleyememeniz, depolayamamanız ve sonra arttıramamanızın bir nedeni olacağını düşünmüyorum. Aynı sonucu elde edersiniz.

Mesela, şöyle bir şey yazdığınız daha normal bir vakanız olduğunu varsayalım: z = (x ++) + (y ++);

Söylendi mi (teknik özellikleri atlamak için sözde kod)

load x
increment x
add y
increment y
store x+y to z

veya

load x
add y
store x+y to z
increment x
increment y

alakasız olmalı. Her iki uygulama da geçerli olmalı diye düşünüyorum.

Bu davranışa bağlı kod yazma konusunda son derece temkinli olurum. Bana göre, uygulamaya çok bağlı, teknik özelliklerdeki çatlaklar arasında görünüyor. Fark yaratacak tek zaman, buradaki örnek gibi çılgın bir şey yaptıysanız veya çalışan iki iş parçacığınız varsa ve ifade içindeki değerlendirme sırasına bağlıysanız.



0

x++Ekspresyon sonucunu x. ++Bölüm sonra değerini etkileyebilecek değerlendirme değil sonra, açıklamada . böylece x = x++etkili bir şekilde çevrilir

int y = x; // evaluation
x = x + 1; // increment part
x = y; // assignment

0

Değeri bir artırmadan önce, değer değişkene atanır.


0

Bu oluyor çünkü yazı artırıldı. Bu, ifadenin değerlendirilmesinden sonra değişkenin artırıldığı anlamına gelir.

int x = 9;
int y = x++;

x şimdi 10'dur, ancak y 9'dur, x değeri artırılmadan önceki değerdir.

Post Increment'un tanımı daha fazlasını görüntüleyin .


1
Kişisel x/ yörnek gerçek kodundan farklıdır ve fark önemlidir. Bağlantınız Java'dan bile bahsetmiyor. Dillerden ikisi için yok bahsetmek söz konusu deyimi tanımlanmamış.
Matthew Flaschen

0

Aşağıdaki kodu kontrol edin,

    int x=0;
    int temp=x++;
    System.out.println("temp = "+temp);
    x = temp;
    System.out.println("x = "+x);

çıktı,

temp = 0
x = 0

post incrementdeğeri artırmak ve değeri artıştan önce döndürmek anlamına gelir . Değer nedeni budur tempolduğunu 0. Peki temp = iya bu bir döngü içinde ise (ilk kod satırı hariç). tıpkı soruda olduğu gibi !!!!


-1

Artış işleci, atadığınız değişkenle aynı değere uygulanır. Bu bela istiyor. Bu programı çalıştırırken x değişkeninizin değerini görebildiğinizden eminim .... bu döngü neden asla bitmez açık olmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.