X++ oder ++X?



  • Hallo Leute,

    ich habe schon ein paar C++ Programme von anderen ForumMitglidern gesehen und habe manchmal das Gefühl als würden manche den Unterschied zwischen X++ und ++X nicht verstehen. 🙄
    Das ist nähmlich ein größerer Unterschied als manche annehmen.

    Um gleich auf den Punkt zu kommen:

    bei ++X wird die Variable X um eins erhöht.
    bei X++ wird der Wert der Variable X zwischen gespeichert (also eine Kopie wird erstellt), und dann wird X um eins erhöht.

    in einer "for"- Schleife ist es daher überflüssig X++ zu schreiben es sei denn man macht es absichtlich wie z.B.:

    for (int X = 0; X++ < 10; ) {}
    

    aber hier ist es überflüssig:

    /* etwas langsamer */
    for (int X = 0; X < 10; X++) {}
    /* etwas schneller */
    for (int X = 0; X < 10; ++X) {}
    

    Der Unterschied der Geschwindigkeit ist zwar minimal aber es ist, vorallem wenn man die Vraibale ausgiebt und gleichzeitig erhöht oder um eins verkleinert, eben doch nicht das Gleiche! 🕶

    (Dieser Thread wurde nicht erstellt weil ich mich darüber ärgere, dient ausschließlich als Information) 🙂
    Gruß LukasBanana



  • Irgendwo gibts nen FAQ Eintrag dazu.

    Schau dir doch mal den Assemblercode davon an, ich würde wetten es gibt keinen unterschied bei int.

    Nie wieder Krieg, nie mehr Las Vegas!



  • MAch doch einen Artikel für das Magazin draus? In 1,5 Wochen könnte er erscheinen.



  • GGGGG schrieb:

    Schau dir doch mal den Assemblercode davon an, ich würde wetten es gibt keinen unterschied bei int.

    das Thema hatte ich letztens erst mit einigen Leute "diskutiert" ++X ist schneller weil du dir theoretisch ein MOV sparst. Theoretisch deshalb weil ein compiler eigentlich erkennen sollte, ob es die "temporäre" variable braucht und aufgrund dieser Erkenntnis die optimierte Version verwendet.



  • MAch doch einen Artikel für das Magazin draus? In 1,5 Wochen könnte er erscheinen.

    Ja, ein Artikel über Debugger wäre super ! Also wie man mit einem Debugger umgeht, was der Assemblercode bedeutet etc.



  • War garnicht so einfach was zu machen, bei dem nicht alles wegoptimiert wird.

    int main(int argc, char *argv[]) {
    	int m = 0;
    	for (int X = 0; X < argc; X++) {
    		m*=argc;
    	}
    
    	return m;
    }
    
    ;	COMDAT _main
    _TEXT	SEGMENT
    _argc$ = 8						; size = 4
    _argv$ = 12						; size = 4
    _main	PROC NEAR					; COMDAT
    
    ; 3    : 	for (int X = 0; X < argc; X++) {
    
    	mov	ecx, DWORD PTR _argc$[esp-4]
    	xor	eax, eax
    	test	ecx, ecx
    	jle	SHORT $L276
    
    ; 2    : 	int m = 0;
    
    	mov	edx, ecx
    	npad	4
    $L274:
    
    ; 4    : 		m*=argc;
    
    	imul	eax, ecx
    	dec	edx
    	jne	SHORT $L274
    $L276:
    
    ; 5    : 	}
    ; 6    : 
    ; 7    : 	return m;
    ; 8    : }
    
    	ret	0
    
    int main(int argc, char *argv[]) {
    	int m = 0;
    	for (int X = 0; X < argc; ++X) {
    		m*=argc;
    	}
    
    	return m;
    }
    
    _TEXT	SEGMENT
    _argc$ = 8						; size = 4
    _argv$ = 12						; size = 4
    _main	PROC NEAR					; COMDAT
    
    ; 3    : 	for (int X = 0; X < argc; ++X) {
    
    	mov	ecx, DWORD PTR _argc$[esp-4]
    	xor	eax, eax
    	test	ecx, ecx
    	jle	SHORT $L276
    
    ; 2    : 	int m = 0;
    
    	mov	edx, ecx
    	npad	4
    $L274:
    
    ; 4    : 		m*=argc;
    
    	imul	eax, ecx
    	dec	edx
    	jne	SHORT $L274
    $L276:
    
    ; 5    : 	}
    ; 6    : 
    ; 7    : 	return m;
    ; 8    : }
    
    	ret	0
    

    => Der Compiler macht was ganz anderes draus, als man denkt, aber beides mal das gleiche.



  • Welche IDE verwendest du ? Hast du des durch den Laufzeitdisassembler gejagt, oder erst die fertige EXE disassembliert ?



  • Hallo

    mikey schrieb:

    MAch doch einen Artikel für das Magazin draus? In 1,5 Wochen könnte er erscheinen.

    Ja, ein Artikel über Debugger wäre super ! Also wie man mit einem Debugger umgeht, was der Assemblercode bedeutet etc.

    Es gibt bereits einen Artikel, der sich mit dem Debuggen beschäftigt und zwar von estartu.

    chrische



  • mikey schrieb:

    Welche IDE verwendest du ? Hast du des durch den Laufzeitdisassembler gejagt, oder erst die fertige EXE disassembliert ?

    VS 2003. Assemblyausgabe: Assembly mit Quellcode (/Fas) eingestellt.



  • Wenn ich eine Variable auf dem Stack anlege:

    int i = 0;
    

    ...sieht der dazugehörige Assemblercode so aus:

    0x40136b	movl   $0x0,0xfffffff8(%ebp)
    

    Ich kenne nur den Befehl MOV, der hat folgende Syntax:

    mov Ziel, Quelle

    Was bedeutet dann 'movl' ? Scheint so, als würde als erster Parameter der zu kopierende Wert (0x0 == 0) stehen, und im zweiten das Ziel...



  • Ist zwar schon ne weile her, dass ich Assembler hatte, aber ich versuchs mal zu erklären.

    ;	COMDAT _main
    _TEXT	SEGMENT
    _argc$ = 8						; size = 4
    _argv$ = 12						; size = 4
    _main	PROC NEAR					; COMDAT
    
    ; 3    : 	for (int X = 0; X < argc; X++) {
    
    	mov	ecx, DWORD PTR _argc$[esp-4] ;argc wird in ecx geschrieben
    	xor	eax, eax ; eax auf 0 setzen eax = m
    	test	ecx, ecx ; schauen ob garnix zu tun ist (argc == 0)
    	jle	SHORT $L276
    
    ; 2    : 	int m = 0;
    
    	mov	edx, ecx ; edx =  argc
    	npad	4 ; keine Ahnung
    $L274:
    
    ; 4    : 		m*=argc;
    
    	imul	eax, ecx ; m*=argc;
    	dec	edx ; 1 von edx abziehen (das X++ oder ++X)
    	jne	SHORT $L274 ; prüfen, ob fertig (ist wohl equal, wenn dec edx 0 liefert)
    $L276:
    
    ; 5    : 	}
    ; 6    : 
    ; 7    : 	return m;
    ; 8    : }
    
    	ret	0
    


  • mikey schrieb:

    Was bedeutet dann 'movl' ? Scheint so, als würde als erster Parameter der zu kopierende Wert (0x0 == 0) stehen, und im zweiten das Ziel...

    soweit ich mich entsinne move long, witzigerweise stehts nicht in meiner Assembler referenz. Warum QUELLE und ZIEL da gedreht ist weiß auch nur Gott... Ich 'liebe' CISC-Wirrwar



  • DoomWarrior schrieb:

    mikey schrieb:

    Was bedeutet dann 'movl' ? Scheint so, als würde als erster Parameter der zu kopierende Wert (0x0 == 0) stehen, und im zweiten das Ziel...

    soweit ich mich entsinne move long, witzigerweise stehts nicht in meiner Assembler referenz. Warum QUELLE und ZIEL da gedreht ist weiß auch nur Gott... Ich 'liebe' CISC-Wirrwar

    Das is nur die GAS-Syntax. Du hast den Code wohl mim gcc kompiliert, der spuckt gas-Syntax aus, weil er als Assembler gas hernimmt 😉
    Grob gesagt:
    Ein Befehl kriegt ein Postfix (das l), das die Größe angibt, Ziel und Quelle werden umgedreht, Register haben ein % davor, ...
    Kann sein, dass die Beschreibung nich genau stimmt, is ewig her, dass ich das letzte mal was damit gemacht hab 😉



    1. der generierte Code wird gleich aussehen
    2. wers ausprobieren will:
    int volatile v;
    void test()
    {
        for(int i = 0; i < 1000; i++)
            v = i;
    }
    

Anmelden zum Antworten