Różnica C++ ,Java ,C# kto wytłumaczy?

0

Witam 3 poniższe kody i ich wyniki:

#include <cstdio>
int main()
{
        int i=0;
        i = i++;
        i = i++;
       i = i++;
       printf("%d",i);
       return 0;
} 

Daje wynik 3

Ten sam kod w C# i Java daje wynik 0 może ktoś to jasno wytłumaczyć? (Jak możecie przetestujcie kody :))

using System;
 
class TestApp
{
        static void Main()
        {
                int i=0;
                i = i++;
                i = i++;
                i = i++;
                Console.WriteLine(i);
        }
}
class main
{
	public static void main(String[] a)
	{
		int i = 0;
		i = i++;
                i = i++;
                i = i++;
		System.out.println(i);
	}
}

Jak możecie dajcie podobne przykłady w innych językach :)

1

ZTCW w C++ wynik zależy od kompilatora (albo nawet jego wersji). Za to w Javie takie operacje są dobrze zdefiniowane (w C# pewnie też, w końcu w dużej mierze C# jest zerżnięty z Javy).

3

http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.15

Standard języka C++ mówi:

Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.

Instrukcja i = i++ próbuje zmodyfikować zmienną i dwukrotnie (tzn zapisać do tej zmiennej). Zgodnie ze standardem C++, program w tym momencie może wykonać dowolną czynność, np wysłać twoją nagą fotę na Facebooka.

Dodatkowe info: http://c-faq.com/expr/index.html
Ale tą stronę już kiedyś podawałem, widocznie, Gelldur, nieuważnie czytasz forum.

1

uzywasz post increment, ktory w sumie nic nie robi, bo zapisujesz za kazdym razem zmienna i

	int i = 0;
	i = i++; //post increment, czyli i++ ma tu  wartosc 0
        i = i++; //i = 0, post increment, czyli i++ ma tu znowu wartosc 0
        i = i++; // itd
       System.out.println(i);

nie powinno sie przypisywac incrementacji do tej samej zmienej. Powinno to byc tak:

	int i = 0;
	i++; //post increment, czyli i++ ma tu jeszcze wartosc 0
        i++; // 1
        i++; // 2
       System.out.println(i); //3
       System.out.println(i++); //3
       System.out.println(++i); // 4 plus  Pre Increment ktory powoduje ze i bedzie tu mialo wartosc 5.
0
mwili napisał(a)

uzywasz post increment, ktory w sumie nic nie robi, bo zapisujesz za kazdym razem zmienna i

	int i = 0;
	i = i++; //post increment, czyli i++ ma tu  wartosc 0
        i = i++; //i = 0, post increment, czyli i++ ma tu znowu wartosc 0
        i = i++; // itd
       System.out.println(i);

nie powinno sie przypisywac incrementacji do tej samej zmienej. Powinno to byc tak:

	int i = 0;
	i++; //post increment, czyli i++ ma tu jeszcze wartosc 0
        i++; // 1
        i++; // 2
       System.out.println(i); //3
       System.out.println(i++); //3
       System.out.println(++i); // 4 plus  Pre Increment ktory powoduje ze i bedzie tu mialo wartosc 5.

Zgadzam się, zapis:

i = i++;

jest niepoprawny. Powinno być

i++;
7

Aby rozwiązać tę zagadkę należy najpierw odpowiedzieć sobie na pytanie pomocnicze: "Dlaczego majtki zakłada się przez nogi, a nie przez głowę?".

Wynikiem działania operatora postinkrementacji w C# jest operand ZANIM został zmieniony. (To jest zasadnicza różnica w stosunku do operatora preinkrementacji, który zwraca operand po zmianie.)

Zatem w takiej linii kodu:

i = i++;

Następują takie operacje:

  1. Tworzona jest kopia wejściowej wartości i (wartości zarówno kopii jak i i wynoszą 0);
  2. Do wartości i przypisywana jest wartość i + 1 (wartość i wynosi teraz 1);
  3. Operator zwraca wartość kopii wejściowej wartości i (czyli 0);
  4. Wartość kopii jest przypisywana do i (czyli mimo, że i było na chwilę zwiększone, to teraz zostało zastąpione wejściową wartością równą 0).

Tak samo zapewne odbywa się to w Javie, natomiast w C++, w którym 80% operacji jest implementation specific undefinded behaviour, tylko jednorożce wiedzą, co się stanie.

0

@somekind To się nazywa wyczerpująca odpowiedź. ;)

3

Kod Javowy:

public class Main {

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

Dezasemblacja + komentarze:

piotrek@p5q-pro:~/NetBeansProjects/IdeoneJava/build/classes$ javap -c Main
Compiled from "Main.java"
public class Main extends java.lang.Object{
public Main();
  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 - załaduj zero
   1:	istore_1 - zapisz w pierwszej zmiennej lokalnej
   2:	iload_1 - załaduj pierwszą zmienną lokalną
   3:	iinc	1, 1 - zwiększ pierwszą zmienną lokalną o jeden
   6:	istore_1 - zapisz pierwszą zmienną lokalną
   7:	iinc	1, 1 - zwiększa pierwszą zmienną lokalną o jeden
   10:	iload_1 - załaduj pierwszą zmienną lokalną
   11:	iconst_1 - załaduj jedynkę
   12:	iadd - dodaj wartości
   13:	istore_1 - zapisz pierwszą zmienną lokalną
   14:	getstatic	#2; //Field java/lang/System.out:Ljava/io/PrintStream;
   17:	iload_1 - załaduj pierwszą zmienną lokalną
   18:	invokevirtual	#3; //Method java/io/PrintStream.println:(I)V - wypisz tą zmienną
   21:	getstatic	#2; //Field java/lang/System.out:Ljava/io/PrintStream;
   24:	iload_1 - załaduj pierwszą zmienną lokalną
   25:	iinc	1, 1 - zwiększ pierwszą zmienną lokalną o jeden
   28:	invokevirtual	#3; //Method java/io/PrintStream.println:(I)V
   31:	getstatic	#2; //Field java/lang/System.out:Ljava/io/PrintStream;
   34:	iinc	1, 1 - zwiększ pierwszą zmienną lokalną o jeden
   37:	iload_1 - załaduj pierwszą zmienną lokalną
   38:	invokevirtual	#3; //Method java/io/PrintStream.println:(I)V
   41:	return

}

Podstawowy myk jest taki, że maszyna Javy to maszyna stosowa. A więc jak wrzucimy zmienną na stos, a potem ją zmienimy, to wartość na stosie nie będzie odzwierciedlać aktualnego stanu zmiennej.

0

Nie wiem po co piszesz cos o stosach itp skoro somekind opdowiedzial na pytanie wszystko co jest tutaj do powiedzenia.
Nie wiem dlaczego somekind ma +4 (obecnie) a mwili -1 skoro powiedzieli to samo.

1 użytkowników online, w tym zalogowanych: 0, gości: 1