C++ /[Java] Schleifenvariablen nach der for Schleife

Kampfgnom

Lt. Commander
Registriert
Jan. 2005
Beiträge
1.075
Hi,
unser Prof hat heute allen Ernstes behauptet dass Variablen, die zum durchlaufen der Schleife verwendet werden, in Java nach der Schleife nicht mehr genau definiert sind. Auch wenn sie vor der Schleife deklariert wurden.
Folgender Code-Schnipsel:
Code:
int i = 0;
for(;i<10;i++){/*...*/}
//i nicht mehr klar definiert/nicht mehr klar, was in i steht.
Prinzipiell verwenden wir Java, auf nachfrage erklärte er aber dass das auch für C++ gilt. Bei C++ bin ich sicher, dass dem nicht so ist. Und für Java sollte meiner Erinnerung nach, das gleiche gelten.
Ich zweifle an meinem Verstand, mehr jedoch an dem meines Profs.

Hat zufällig einer einen Verweis in eine Dokumentation, die meine Meinung unterstreichen kann? Sowas ist echt schwer zu finden :)

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

Da ich auch nach der Schleife auf i zugreifen kann ... geht es wohl ;)
 
Zuletzt bearbeitet:
Bin mir sicher das dein Prof falsch liegt.
Einfach mal deinen geposteten Quelltext Compilieren und gucken was passiert.;)
 
Dein Prof. bezog sich vermutlich auf diese Beispiel:
Code:
for(int i = 0;i<10;i++){/*...*/}
//i nicht mehr klar definiert/nicht mehr klar, was in i steht.
und dort ist die Aussage absolut korrekt, da das i nur innerhalb Schleife definiert ist. Jeder Zugriff ausserhalb der Schleife führt zu einem nicht kompilerbaren Programm bei java.

edit:

In deinem Beispiel
Code:
int i = 0;
for(;i<10;i++){/*...*/}
ist die Aussage schlicht unsinn und das i natürlich noch definert.
 
Zuletzt bearbeitet:
Er bezieht sich aber exakt auf vor der Schleife deklariert, von daher hat sein Prof doch unrecht.
 
Ich programmiere nun auch schon ein "paar" jährchen, und habe daher explizit nachgefragt, ob er es so meint.
Da der Typ Professor für Softwaretechnik und Programmieren ist, gehe ich davon aus, dass ein Missverständnis vorliegt, dennoch wollte ich mal nachgefragt haben, ehe ich mich mit ihm zu unrecht kurzschließe ;)

Achja: Falls noch einer genauer über das Problem nachdenken will: Prof sagte etwas davon dass Schleifenvariablen komisch rumkopiert und inkrementiert werden in einer for Schleife, daher kann wohl irgendwie nach dem Standard kein genaues i nach der Schleife garantiert werden. Aber der Mensch faselt eh manchmal etwas konfuses Zeug um sich rauszureden...
 
Zuletzt bearbeitet:
Ich denke genaue Auskunft müsste eine technische JAVA-Dokumentation geben, in der genau steht, wie der Speicherplatz allokiert wird und wie mit Variablen und derem Inhalt verfahren wird, wenn in verschiedenen Anweisungsblöcken und demzufolge auch in den verschiedenen "Hierarchieebenen" der Code dann auf den Byte-Code heruntergebrochen wird und später dann von der VM ausgeführt wird. Nur ein Gedanke...

Von der täglichen Erfahrung her, stimme ich aber allen hierzu. Zumindest ist mir bisher noch nichts anderes unter gekommen.
 
Also theoretisch möglich wäre es, dass durch loop-unrolling solches verhalten entstehen kann. Praktisch auftreten kann so etwas aber nur dann wenn hoch optimierende Compiler verwendet werden mit sehr aggresiven Optimierungen. Zum Beispiel so etwas:
Code:
for(int i=0; i < N;i++) {
    c[i] = a[i] + b[i];
}

zu 

for(int i=0; i < N; i+=4) {
    if(i<N) {
     c[i] = a[i] + b[i];
    }
    if(i+1<N) {
     c[i+1] = a[i+1] + b[i+1];
    }
    if(i+2<N) {
     c[i+2] = a[i+2] + b[i+2];
    }
    if(i+3<N) {
     c[i+3] = a[i+3] + b[i+3];
    }
}

bzw (edit)

for(int i=0; i<N; i+=4) {
	switch( N - i ) {
		default:
			a[i+3] = b[i+3] + c[i+3];
		case 3:
			a[i+2] = b[i+2] + c[i+2];
		case 2:
			a[i+1] = b[i+1] + c[i+1];
		case 1:
			a[i] = b[i] + c[i];
	}
}

Unter solchen Umständen kann die Aussage zutreffen. Eventuell bezog sein dein Prof darauf. Es hängt dann aber enorm vom Verhalten des Compilers ab und lässt keine genrellen Aussagen mehr zu. Abgesehen davon sollte man solche Schweinereien ohnehin nicht machen :evillol:
 
Zuletzt bearbeitet: (2. Beispiel hinzugefügt)
mhh bei Optimierungen sollte man immer vorsichtig sein .. schon alleine weil der Code schnell schwer wartbar wird und sich das Fehlerpotenzial ernorm erhöht.


Gruß
 
Nicht DU machst diese Optimierung, sondern der Compiler selbst.
Diese Transformation wird vor der eigentlichen Compilierung durchgeführt!
Loop-Unrolling sind da noch die harmloseren Beispiele. Und gerade wenn die Sprache zu diesem verhalten undefiniert ist, kann der Compiler quasi machen was erwill. In so fern wäre es wirklich interessant zu wissen wie genau das Verhalten bei Java definiert ist. Mich selbst würde das nämlich auch mal interessieren ;) Bitte mal den Link zu einer genauen Sprachdefinition posten sofern bekannt - DANKE.
 
Mit schwer wartbar meinte ich eigentlich das der Ablauf nachträglich mit nem Debugger manchmal nicht verfolgbar ist.
Sowas schwebt mir noch vor(falls ich mich irre bitte ich um Berichtigung :D).

Gruß
 
Warum soll denn der oben optimierte Code schneller sein?
Es müssen doch mehr berechnungen druchgeführt werden als in den 3 Zeilen code.
 
Das ist ein einfaches Beispiel. In der Praxis kann soetwas erheblich schneller sein, da Branch-Misspredictions vermieden werden und die CPU-Pipeline nicht neu befüllt werden müssen, denn soetwas kostet richtig Zeit. Wie genau der Compiler ein IF-Statement übersetzt kommt immer auf den Kontext an. Ausserdem führen alle moderneren Archtikturen Code in parallel arbeiteten Piplenes aus, auch das bewirkt das es für einen Menschen nahezu unmöglich ist besseren Code per hand zu schreiben als es eine Maschine schafft. Codeoptimierung ist extrem schwierig, das fängt schon damit an das kein Compiler aufsteigende Schleifen generiert sondern nahezu immer absteigende, da die erheblich schneller verarbeitet werden können. Diese Liste lässt sich jetzt beliebig fortsetzen. Aber nur weil der "Code" langsamer aussieht, muss das noch lange nicht der Fall sein.
 
Code:
//Also würde das:
for(int i = 0; i < 5000; i++){/*....*/}
//zu dem werden?!
for(int i = 5000; i > 0; i--){/*....*/}
 
krizzelfix schrieb:
Code:
//Also würde das:
for(int i = 0; i < 5000; i++){/*....*/}
//zu dem werden?!
for(int i = 5000; i > 0; i--){/*....*/}

Eher nein, da eine Maschine lieber auf <> 0 prüft:
Code:
for(int i = 0; i < 5000; i++){ System.out.println(i); }

würde also eher zu folgendem

for(int i = 5000; i-- <> 0;){ int __i = 5000 - 1-i; System.out.println( __i ); }

realistisch gesehen aber sehr wahrscheinlich eher zu folgendem (zuzüglich blocking etc.):

for(int i = 5000, __i=0; i-- <> 0;__i++){ System.out.println( __i ); }

aber das hängt auch davon ab was in der Schleife selbst steht, Pauschal-Aussagen gibts hier keine. Aber um optimale Ergebnisse zu bekommen sollte man die Arbeitsweise des eingesetzten Compilers kennen. Auf keinen Fall sollte man auf die Idee kommen solche Optimierungen per Hand zu machen, wenn es der Compiler schon macht, denn meistens ist das Quälcode anschließend nahezu unwartbar.
 
Kampfgnom schrieb:
Achja: Falls noch einer genauer über das Problem nachdenken will: Prof sagte etwas davon dass Schleifenvariablen komisch rumkopiert und inkrementiert werden in einer for Schleife, daher kann wohl irgendwie nach dem Standard kein genaues i nach der Schleife garantiert werden.
Da wird nichts komisch rumkopiert oder inkrementiert. In den Spezifikationen von Java steht nichts derartiges drin. Wenn der Compiler sich komisch verhält, dann liegt das an ihm und nicht an den Java-Spezifikationen.
 
Zurück
Oben