Wieso schreiben C++ Progger for(int i=0; i!=99... anstatt i<99



  • Ich glaube im C++ Primer steht das auch irgendwo drin, Iteratoren waren da AFAIR auch die Begründung.



  • groovemaster schrieb:

    kreater schrieb:

    warum schreiben manche for(;;) statt while(true)?

    Weil das diverse Compiler weniger zu Warnungen veranlasst.

    Bzw. weil "for(;;)" einfach viel kuuhler ist 😉



  • hustbaer schrieb:

    groovemaster schrieb:

    kreater schrieb:

    warum schreiben manche for(;;) statt while(true)?

    Weil das diverse Compiler weniger zu Warnungen veranlasst.

    Bzw. weil "for(;;)" einfach viel kuuhler ist 😉

    Weil das die C-Programmierer auch schon so gemacht haben.
    Und die hatten schließlich coole Frisuren und flotte Hüte!



  • Ich hatte es auch irgendwo gelesen. Zum einen ist ein for(;; ) einfach kürzer, zum anderen passt es besser zu forever . 😃



  • lagalopex schrieb:

    Ich hatte es auch irgendwo gelesen. Zum einen ist ein for(;; ) einfach kürzer, zum anderen passt es besser zu forever . 😃

    Wie meinst du das? So?

    #define forever for(;;)
    

    for(;; ) finde ich jetzt aber hässlicher als while(true) - bei der While-Variante sieht man meiner Ansicht nach auch schneller, worum es sich handelt. Aber das ist natürlich Geschmackssache (einmal abgesehen davon, dass solche Endlosschleifen sowieso kaum geschrieben werden). 😉



  • Oder gleich

    #define ever (;;)
    
    for ever
    {
    }
    

    🤡



  • hustbaer schrieb:

    Oder gleich

    #define ever (;;)
    
    for ever
    {
    }
    

    🤡

    :p



  • CppProgger schrieb:

    Das hat doch nen Grund?

    der grund ist fehlende weitsicht. viele c++ entwickler sind seltsamerweise der meinung, dass code nicht kindersicher sein muss, da man ihn ja selbst geschrieben hat und auch ein blinder mit krückstock sofort durchblickt.

    for( int i = 0; i != 99; ++i )
    {
       // paar zeilen code
    }
    

    ist unglaublich fehleranfällig. ein unbedarfter zweiter (oder derselbe entwickler, kommt vor) könnte auf die idee kommen, den code irgendwie zu "verbessern" und folgendes einbauen

    for( int i = 0; i != 99; ++i )
    {
       // paar zeilen code
       if( somethingImportant )
         i += 3;
    }
    

    und schon hat man die wunderschönsten fehler im programm.



  • Vielleicht wird != um eine Tausendstel Sekunde schneller ausgewertet als <. Wäre gar nicht so unlogisch. Bei != kann die Funktion beim erstbesten Bit zurückkehren, das nicht übereinstimmt. Bei < ist die Sache nicht so eindeutig, bzw. müssen im Durchschnitt immer ein paar Bits mehr miteinander verglichen werden -> ergo -> dauert deshalb eventuell minimal länger. Ist aber nur eine Theorie. Man würde gar nicht vermuten, in wie vielen Fällen ein Stück Code sich in Punkto Laufzeit von einem anderen Stück Code unterscheidet, das eigentlich genau das gleiche tut, aber eben mithilfe anderer Operatoren.

    Kleines Beispiel:

    int a = f();
    if(a < 3)
     a += 3;
    else
     a += 6;
    

    Scheinbar gleichwertig ist z.B.:

    int a = f();
    a += a < 3 ? 3 : 6;
    

    Der Laufzeitunterschied ist zwar minimal, aber die zweite Version ist z.B. bei 200 Mio. Schleifendurchläufen auf meinem Rechner um ca. 1/100 Sekunde schneller (extra getestet).

    Es ist gut vorstellbar, dass solche mikroskopischen Laufzeitunterschiede auch zwischen dem < und dem != Operator bestehen (falls der Compiler solche Fälle automatisch erkennen sollte und dementsprechend ohne Zutun des Proggers bei der Übersetzung optimiert ist es wohl einerlei, ob man < oder != schreibt.)



  • Theorien-Erfinder schrieb:

    Bei != kann die Funktion beim erstbesten Bit zurückkehren

    Was für Funktionen denn? Das ganze wird in Maschinencode übersetzt und da macht es zeitlich keinen Unterschied, ob du auf Gleichheit oder Kleinerheit (wie heisst das auf Deutsch?) überprüfst.



  • Nanyuki schrieb:

    Theorien-Erfinder schrieb:

    Bei != kann die Funktion beim erstbesten Bit zurückkehren

    Was für Funktionen denn? Das ganze wird in Maschinencode übersetzt und da macht es zeitlich keinen Unterschied, ob du auf Gleichheit oder Kleinerheit (wie heisst das auf Deutsch?) überprüfst.

    So, und ab sofort ist es keine Theorie mehr, sondern eine Tatsache:
    != ist geringfügig schneller als <

    Dieses Programm diente zur Überprüfung:

    #include <windows.h>
    #include <stdio.h>
    
    int main(){
    	long dummy = 0;
    	LARGE_INTEGER a,b;
    
    	/* Erste Version */
    	QueryPerformanceCounter(&a);
    	for(int i = 0; i != 200000000; ++i)
    		dummy += i & 1 ? 1 : 0;
    	QueryPerformanceCounter(&b);
    	printf("Dauer !=: %I64d QueryTakte\n"
    		"Es gibt %d ungerade Zahlen\n",
    		b.QuadPart-a.QuadPart,
    		dummy);
    
    	/* Zweite Version */
    	dummy = 0;
    
    	QueryPerformanceCounter(&a);
    	for(int i = 0; i < 200000000; ++i)	/* Einziger Unterschied: < statt != */
    		dummy += i & 1 ? 1 : 0;
    	QueryPerformanceCounter(&b);
    	printf("Dauer <: %I64d QueryTakte\n"
    		"Es gibt %d ungerade Zahlen\n",
    		b.QuadPart-a.QuadPart,
    		dummy);
    
    	fgetc(stdin);
    
    	return 0;
    }
    

    Und das war der Output:

    Dauer !=: 2358403 QueryTakte
    Es gibt 100000000 ungerade Zahlen
    Dauer <: 2465883 QueryTakte
    Es gibt 100000000 ungerade Zahlen
    

    Es wurde zuerst die Laufzeit der != Schleife gestoppt,
    und danach die Laufzeit einer ansonsten äquivalenten < Schleife.
    Der Unterschied beträgt ca. 100.000 Query-Takte, (das entspricht auf meinem Rechner ungefähr eine Vierzigstel-Sekunde).

    --> Falls 2.465.883 größer als 2.358.403 sein sollte, so ist auch der != Operator schneller als der < Operator. Genau wie ich vermutet hatte. Solche Schreibweisen-Tricks haben meistens mit Laufzeit-Optimierung zu tun.



  • So ein Schwachsinn, eine 1/40 Sekunde - das ist doch mit geraumer Wahrscheinlichkeit nur ein Messfehler.
    Wiederhole die Messung erstmal auf paar hundert verschiedenen Rechnern mit mehreren tausend Testläufen, bevor du hier irgendwelche wilden Behauptungen in den Raum stellst!

    Das hier ist im Übrigen meine Ausgabe:

    Dauer !=: 957994 QueryTakte
    Es gibt 100000000 ungerade Zahlen
    Dauer <: 946040 QueryTakte
    Es gibt 100000000 ungerade Zahlen
    

    --> Falls 957.994 größer als 946.040 sein sollte, so ist deine Theorie ziemlicher Mist. Genau wie ich vermutet hatte. Solche Schreibweisen-Tricks bringen in der Praxis absolut rein gar nichts.



  • Aber Interessant, bei mir liegt die <-Version fast immer hinten. Vielleicht ist da doch ganz ganz ganz wenig Wahres dran.
    Die obige Messung ist übrigens noch gut, meistens liegt die <-Version 15k-25k Takte dahinter.



  • Theorien-Erfinder schrieb:

    Vielleicht wird != um eine Tausendstel Sekunde schneller ausgewertet als <. Wäre gar nicht so unlogisch. Bei != kann die Funktion beim erstbesten Bit zurückkehren, das nicht übereinstimmt. Bei < ist die Sache nicht so eindeutig, bzw. müssen im Durchschnitt immer ein paar Bits mehr miteinander verglichen werden -> ergo -> dauert deshalb eventuell minimal länger. Ist aber nur eine Theorie.

    Nette Theorie, sie ignoriert leider die Funktionsweise von Rechnern 😉

    Newsflash: Auch von Compilern. gcc scheint zumindest solche Standardmuster zu erkennen und generiert gleich nur eine jne-Instruktion (jump if not equal).



  • Gegner der Wissenschaft schrieb:

    Aber Interessant, bei mir liegt die <-Version fast immer hinten. Vielleicht ist da doch ganz ganz ganz wenig Wahres dran.
    Die obige Messung ist übrigens noch gut, meistens liegt die <-Version 15k-25k Takte dahinter.

    Klar müsste man das auf mehreren Rechnern überprüfen. Es könnte auch sein, dass ein und der gleiche Maschinenbefehl auf unterschiedlichen Rechnern jeweils geringfügig anders implementiert ist. Ich wollte nur darauf hinaus, dass unterschiedliche Maschinenbefehle idR unterschiedliche Laufzeiten haben, was meinem zitierten Vorredner vermutlich nicht bewusst war. Das Beispiel ist natürlich völlig unsinnig, aber um diese winzigen Laufzeitunterschiede aufzudecken, muss die Schleife möglichst oft durchlaufen werden.
    Es gibt aber durchaus auch sinnvolle Anwendungen, in denen milliardenfach irgendwelche Schleifen durchlaufen werden sollen, dann könnte es interessant werden, sich mit diesen geringfügigen Laufzeitunterschieden zu beschäftigen.
    Ich habe absichtlich ein zweites Beispiel im Code untergebracht, das noch deutlicher die unterschiedlichen Laufzeiten von Maschinenbefehlen zeigen könnte.

    Man ersetze
    i & 1
    jeweils durch
    i % 2

    Oberflächlich betrachtet geschieht das gleiche: Man möchte herausfinden, ob eine Zahl ungerade ist. Es wird auch jeweils nur ein einziger Maschinenbefehl verwendet (BITAND bzw. MODULO). Trotzdem ist die Laufzeit der i % 2 - Variante erheblich länger.
    Es gibt noch hunderte solcher Fälle.

    mfg



  • Bashar schrieb:

    Theorien-Erfinder schrieb:

    Vielleicht wird != um eine Tausendstel Sekunde schneller ausgewertet als <. Wäre gar nicht so unlogisch. Bei != kann die Funktion beim erstbesten Bit zurückkehren, das nicht übereinstimmt. Bei < ist die Sache nicht so eindeutig, bzw. müssen im Durchschnitt immer ein paar Bits mehr miteinander verglichen werden -> ergo -> dauert deshalb eventuell minimal länger. Ist aber nur eine Theorie.

    Nette Theorie, sie ignoriert leider die Funktionsweise von Rechnern 😉

    Newsflash: Auch von Compilern. gcc scheint zumindest solche Standardmuster zu erkennen und generiert gleich nur eine jne-Instruktion (jump if not equal).

    Auch Bashar glaubt, dass sich Maschinenbefehle nicht in der Laufzeit unterscheiden. 🙂 Und ich hab' keine Ahnung von der Funktionsweise eines Rechners. Ein Compiler, der optimiert, ohne dass man es ihm anschafft, ist der größte Feind eines Programmierers.
    mfg 😃



  • ihr seid ja alle lol, ich meinte "warum schreiben manche for(;;) statt while(true)" nicht wirklich als frage, denn wie ich weiter geschrieben hab "ist doch scheiss egal... 🙄



  • TheorienErfinder schrieb:

    Auch Bashar glaubt, dass sich Maschinenbefehle nicht in der Laufzeit unterscheiden. 🙂

    Wo liest du das raus?



  • Oh man, geringfügig schneller oder langsamer...
    Wenn ihr das wissen wollt, guckt Euch den Assembler der betreffenden Stelle an, und sucht Euch die Cycles raus, die die Befehle haben. Alles andere ist Hokuspokus.



  • kreater schrieb:

    warum schreiben manche for(;;) statt while(true)?

    is doch scheiss egal...

    Nicht wirklich, denn "while(true)" liefert überflüssige Compilerwarnungen, die man nicht wirklich braucht. "while(true)" ist somit die objektiv schlechtere Variante.


Anmelden zum Antworten