PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : "Optimierungen"


aths
2003-03-10, 18:57:22
Welche Ausgabe erzeugt dieser Code?

#include <iostream.h>

main() {
int a=1;
int b=a++ * a++;
cout << b << endl << a << flush;
}

stabilo_boss13
2003-03-10, 19:49:27
Originally posted by aths
Welche Ausgabe erzeugt dieser Code?

#include <iostream.h>

main() {
int a=1;
int b=a++ * a++;
cout << b << endl << a << flush;
} Oh ein Test! :D
1
3
Warum?

Demirug
2003-03-10, 19:59:44
aths, hat die Frage einen tieferen Sinn? Oder ist mir der Witz entgangen?

zeckensack
2003-03-10, 21:07:13
2 3

aths
2003-03-10, 21:09:31
Ihr fliegt alle von der Schule :D

Eine Chance habt ihr noch...

Hint: gcc benutzen.

Demirug
2003-03-10, 21:10:02
Originally posted by zeckensack
2 3

Wie kommst du darauf?

firewars
2003-03-10, 21:11:27
Originally posted by Demirug Wie kommst du darauf?

Sehr gute Frage.. :|.. mal davon abgesehen, dass b dann, äh, 6 wäre? Kommt es nicht auf die Stellung der "++"-Zeichen an?

Xmas
2003-03-10, 21:13:59
Also wenn schon dann bitte ordentlich:

C++:

#include <iostream>
using namespace std;

int main()
{
int a = 1;
int b = a++ * a++;
cout << b << endl << a << flush;
return 0;
}


C:

#include <stdio.h>

void main()
{
int a = 1;
int b = a++ * a++;
printf("%d\n%d\n", b, a);
}


Ergebnis mit VC++:
1
3

Ergebnis mit gcc-2.95:
1
2

:|

stabilo_boss13
2003-03-10, 21:19:21
Originally posted by aths
Ihr fliegt alle von der Schule :D

Eine Chance habt ihr noch...

Hint: gcc benutzen. Also doch ein Test! :D

int main()
{
int a = 1;
int b = a++ * a++;
cout << b << endl << a << flush;
return 0;
}

ist wie:

int main()
{
int a = 1;
int b = 1 * 1;
a = a + 1;
a = a + 1;
cout << b << endl << a << flush;
return 0;

}

Ergo:
1
3

Auch mit gcc!
-dumpversion
2.95.2

aths
2003-03-10, 21:27:59
Originally posted by stabilo_boss13
ist wie:So sollte es sein. Einige Compilier erkennen allerdings "Oh! Zwei gleiche Ausdrücke!" und berechnen den nur ein mal.

zeckensack
2003-03-10, 21:31:24
Originally posted by Demirug
Wie kommst du darauf? Mir war so, als würde das Postfix-Inkrement sofort nach der Auswertung abgegriffen. Das zweite a hinter dem * wäre dann schon einmal inkrementiert.

1*2 3

Habe ich schon erwähnt, das ich Postfix-Inkrement hasse, und jeden schlagen könnte der sowas macht?
//Da könntsch ausrastn!!!!11 :jedifire:
for (int i=0;i<10;i++)
{
<...>
}

Xmas
2003-03-10, 21:38:57
Originally posted by zeckensack
Habe ich schon erwähnt, das ich Postfix-Inkrement hasse, und jeden schlagen könnte der sowas macht?
//Da könntsch ausrastn!!!!11 :jedifire:
for (int i=0;i<10;i++)
{
<...>
}
Genau, das sollte so aussehen:

for (int i=0;i++<10; )
{
<...>
}
;D

GloomY
2003-03-10, 21:40:01
Originally posted by stabilo_boss13
Also doch ein Test! :D

int main()
{
int a = 1;
int b = a++ * a++;
cout << b << endl << a << flush;
return 0;
}

ist wie:

int main()
{
int a = 1;
int b = 1 * 1;
a = a + 1;
a = a + 1;
cout << b << endl << a << flush;
return 0;

}
Falsch.
Es ist in C nur in wenigen Ausnahmen definert, welche Ausdrücke zuerst und welche danach ausgewertet werden. Nur bei &&, ||, ? : und , ist die Reihenfolge festgelegt. Alles andere ist maschinen- bzw. compilerabhängig. Es kann auch passieren, dass beide Ausdrücke gleichzeitig ausgewertet werden.
Der Compiler könnte imho genauso gut folgendes daraus machen:

int main()
{
int a = 1;
a = a + 1;
a = a + 1;
int b = a * a;
cout << b << endl << a << flush;
return 0;

}

Originally posted by Xmas
Genau, das sollte so aussehen:

for (int i=0;i++<10; )
{
<...>
}
;D Wo ist da der Unterschied / Vorteil?

stabilo_boss13
2003-03-10, 21:44:35
Originally posted by aths
So sollte es sein. Einige Compilier erkennen allerdings "Oh! Zwei gleiche Ausdrücke!" und berechnen den nur ein mal. Sollten sie aber nicht! Was passiert, wenn man verschieden klammert?

int b = (a++ * a++);
int b = (a++) * (a++);

Also ich meine jetzt bei deinen optimierenden Compilern.
Bei mir macht das nämlich keinen Unterschied!
Sollte ja auch nicht (Punkt vor Strich), sonst würden ja

int b = a++ * a; // b = a * a, dann wird a inkrementiert, was aber b nicht mehr betrifft
und
int b = a * a++; // b = a * a, dann wird a inkrementiert, was aber b nicht mehr betrifft

zwei verschiedene Ergebniss liefern.

stabilo_boss13
2003-03-10, 21:55:26
Originally posted by GloomY
Falsch.
Es ist in C nur in wenigen Ausnahmen definert, welche Ausdrücke zuerst und welche danach ausgewertet werden. Nur bei &&, ||, ? : und , ist die Reihenfolge festgelegt. Alles andere ist maschinen- bzw. compilerabhängig. Es kann auch passieren, dass beide Ausdrücke gleichzeitig ausgewertet werden.
Der Compiler könnte imho genauso gut folgendes daraus machen:

int main()
{
int a = 1;
a = a + 1;
a = a + 1;
int b = a * a;
cout << b << endl << a << flush;
return 0;

}


Das wäre mir neu!
Es würde ja bedeuten, dass bei

int b = 5 * 3 + 8;

je nach Compiler als Ergebnis 23 oder 55 herauskäme!

Also in C/C++ gilt bei der Priorität der Operatoren wie in der Mathematik Punkt vor Strich.

GloomY
2003-03-10, 21:55:42
Originally posted by stabilo_boss13
Also ich meine jetzt bei deinen optimierenden Compilern.
Bei mir macht das nämlich keinen Unterschied!
Sollte ja auch nicht (Punkt vor Strich), sonst würden ja

int b = a++ * a; // b = a * a, dann wird a inkrementiert, was aber b nicht mehr betrifft
und
int b = a * a++; // b = a * a, dann wird a inkrementiert, was aber b nicht mehr betrifft

zwei verschiedene Ergebniss liefern. Auch hier ist es vollkommen egal, ob du a++ * a oder a * a++ schreibst. Der Compiler kann selbst bei a * a++ zuerst a++ auswerten (a als Wert und den Seiteneffekt der Inkrementierung) und dann erst mit dem links stehenden a multiplizieren.

GloomY
2003-03-10, 21:57:45
Originally posted by stabilo_boss13

Das wäre mir neu!
Es würde ja bedeuten, dass bei

int b = 5 * 3 + 8;

je nach Compiler als Ergebnis 23 oder 55 herauskäme!

Also in C/C++ gilt bei der Priorität der Operatoren wie in der Mathematik Punkt vor Strich. Nein, die Operatorenreihenfolge ist klar festgelegt. Im Gegensatz zur Reihenfolge der Ausdrucksauswertung.
z.B. ist es nicht festgelegt, ob beim Ausdruck

f() + g()zuerst f oder zuerst g aufgerufen wird.
Bei folgendem Beispiel

f() + g() / h()ist wiederum nicht definiert, in welcher Reihenfolge f,g oder h aufgerufen werden. Allerdings ist die Berechnungsreihenfolge klar festgelegt: Zuerst wird g() durch h() dividiert und dann f() dazu addiert.

Alles klar? ;)

stabilo_boss13
2003-03-10, 22:19:34
Originally posted by GloomY
Nein, die Operatorenreihenfolge ist klar festgelegt. Im Gegensatz zu Reihenfolge der Ausdrucksauswertung.
z.B. ist es nicht festgelegt, ob beim ausdruck

f()+ g()zuerst f oder zuerst g aufgerufen wird. Das sag ich doch!

f()+g();

liefert doch wohl das gleiche Ergebnis wie

g()+f();

Ergo muss

a++ * a;

das selbe Ergebnis wie

a * a++;

liefern.
Also wird der Ausdruck a * a vor dem Inkrement berechnet, egal auf welcher Seite es steht.

Das gilt aber natürlich nur für den Fall, dass der Inkrement-Operator hinter der Variablen steht (Post-Increment). Denn dann wird zwar die Variable erhöht, jedoch der vorherige noch nicht um 1 erhöhte Wert zurückgegeben.


a++

entspricht

int increment(int a)
{
a = a + 1;
return(a - 1);
}


Aus der FH-Vorlesung:
Prä-Increment und Post-Increment als Funktionen


int zahl2 = ++zahl1;
// entspricht
int zahl2 = PreInc(zahl1);
// mit
int PreInc(int& i)
{
i = i + 1;
return i;
}

int zahl2 = zahl1++;
// entspricht
int zahl2 = PostInc(zahl1);
// mit
int PostInc(int& i)
{
int temp = i;
i = i + 1;
return temp;
}

EgonOlsen
2003-03-10, 22:31:40
Falls ein kleiner Blick über den Tellerrand interessiert: Java macht daraus

2
3

Xmas
2003-03-10, 22:35:11
Originally posted by GloomY
Der Compiler könnte imho genauso gut folgendes daraus machen:

int main()
{
int a = 1;
a = a + 1;
a = a + 1;
int b = a * a;
cout << b << endl << a << flush;
return 0;

}

Nein, das geht definitiv nicht. a++ hat als Rückgabewert den Wert von a vor dem Inkrement.

Die zwei sinnvollen Varianten für (a++ * a++) sind IMO:

(wie zeckensack meinte, und auch ich am besten finden würde: )
a von 1 auf 2 inkrementieren, 1 zurückgeben
a von 2 auf 3 inkrementieren, 2 zurückgeben
1 mit 2 multiplizieren, 2 zurückgeben

oder

1 mit 1 multiplizieren, 1 zurückgeben
a von 1 auf 2 inkrementieren
a von 2 auf 3 inkrementieren


Im übrigen halte auch ich den Gebrauch des Postfix-Operators - außer als einzelne Anweisung - für eine unnötige Fehlerquelle.


Wo ist da der Unterschied / Vorteil?
Der Smilie dahinter ;)

stabilo_boss13
2003-03-10, 22:48:02
Originally posted by Xmas

Nein, das geht definitiv nicht. a++ hat als Rückgabewert den Wert von a vor dem Inkrement.

Die zwei sinnvollen Varianten für (a++ * a++) sind IMO:

(wie zeckensack meinte, und auch ich am besten finden würde: )
a von 1 auf 2 inkrementieren, 1 zurückgeben
a von 2 auf 3 inkrementieren, 2 zurückgeben
1 mit 2 multiplizieren, 2 zurückgeben

oder

1 mit 1 multiplizieren, 1 zurückgeben
a von 1 auf 2 inkrementieren
a von 2 auf 3 inkrementieren


Im übrigen halte auch ich den Gebrauch des Postfix-Operators - außer als einzelne Anweisung - für eine unnötige Fehlerquelle.



Der Smilie dahinter ;) [/SIZE]Wenn man die Increments durch Funktionen ersetzt, dann sollte tatsächlich, so wie zeckensack sagt, 2 und 3 als Ergebnis herauskommen.
Die Frage, die sich mir stellt ist, ob C++ Increments als Funktionen oder Additionen betrachtet.

GloomY
2003-03-10, 23:12:44
Originally posted by Xmas

Nein, das geht definitiv nicht. a++ hat als Rückgabewert den Wert von a vor dem Inkrement.[/SIZE]Ja, du hast Recht.
Originally posted by Xmas
Die zwei sinnvollen Varianten für (a++ * a++) sind IMO:

(wie zeckensack meinte, und auch ich am besten finden würde: )
a von 1 auf 2 inkrementieren, 1 zurückgeben
a von 2 auf 3 inkrementieren, 2 zurückgeben
1 mit 2 multiplizieren, 2 zurückgeben

oder

1 mit 1 multiplizieren, 1 zurückgeben
a von 1 auf 2 inkrementieren
a von 2 auf 3 inkrementieren
Zur ersten stimme ich zu. Aber die zweite Variante ist definitiv falsch. Der Postincrement-Operator hat in C die höchste Priorität, d.h. er wird vor allen anderen ausgeführt (also auch vor der Multiplikation). Ich darf also nicht zuerst multiplizieren und dann erst inkrementieren. Das ist definitiv falsch.
Originally posted by Xmas
Im übrigen halte auch ich den Gebrauch des Postfix-Operators - außer als einzelne Anweisung - für eine unnötige Fehlerquelle.

Der Smilie dahinter ;) Oki =)

@stabilo_boss13: Ich habe nicht gesagt, dass bei 'a * a ++' etwas anderes herauskommt als bei 'a ++ * a'. Meine Aussage war folgende:

Die Reihenfolge der Auswertung der Ausdrücke bei zwei- oder mehrstelligen Operatoren ist bis auf die angesprochenen Ausnahmen nicht festgelegt.

Ob jetzt also zuerst der Ausdruck 'a' oder zuerst der Ausdruck 'a ++' ausgewertet wird, ist kompilerabhängig. Natürlich gibt es da einen Unterschied im Ergebnis. Einmal kommt a² raus, einmal a*(a+1).
Das war aber nicht das auf was ich hinauswollte.

GloomY
2003-03-10, 23:30:46
Und noch was:
Originally posted by stabilo_boss13
Aus der FH-Vorlesung:
Prä-Increment und Post-Increment als Funktionen


int zahl2 = ++zahl1;
// entspricht
int zahl2 = PreInc(zahl1);
// mit
int PreInc(int& i)
{
i = i + 1;
return i;
}

int zahl2 = zahl1++;
// entspricht
int zahl2 = PostInc(zahl1);
// mit
int PostInc(int& i)
{
int temp = i;
i = i + 1;
return temp;
}
Kann nicht funktionieren. C verwendet für Funktionen Call-by-Value und kein Call-by-Value-Return. D.h. dass für die Parameter einer Funktion die Werte kopiert werden.
Mit

int zahl2 = PreInc(zahl1);
kann ich also nie zahl1 erhöhen, egal wie PreInc aussieht. Was ich machen kann, ist der Funktion einen Zeiger auf zahl1 übergeben (Call-by-Reference).

z.B. so:

int zahl2 = ++zahl1;
// entspricht
int *zeiger_auf_zahl1 = &zahl1;
int zahl2 = PreInc(zeiger_auf_zahl1);
// mit
int PreInc(int *i)
{
(*i)++;
return *i;
}


Hmm, FH = Fasthochschule? :D (Sorry, konnte es mir nicht verkneifen ;) )

Xmas
2003-03-11, 00:05:31
Originally posted by GloomY
Und noch was:
Kann nicht funktionieren. C verwendet für Funktionen Call-by-Value und kein Call-by-Value-Return. D.h. dass für die Parameter einer Funktion die Werte kopiert werden.
Mit

int zahl2 = PreInc(zahl1);
kann ich also nie zahl1 erhöhen, egal wie PreInc aussieht. Was ich machen kann, ist der Funktion einen Zeiger auf zahl1 übergeben (Call-by-Reference).

z.B. so:

int zahl2 = ++zahl1;
// entspricht
int *zeiger_auf_zahl1 = &zahl1;
int zahl2 = PreInc(zeiger_auf_zahl1);
// mit
int PreInc(int *i)
{
(*i)++;
return *i;
}

Der Code von stabilo_boss13 ist korrekt. Call-by-Reference geht in C++ mit - genau - Referenztypen!

Schreibweise:
int& i

Das ist eine Referenz auf ein int, kein int. Die Umwandlung ist implizit.

GloomY
2003-03-11, 07:57:11
Originally posted by Xmas

Der Code von stabilo_boss13 ist korrekt. Call-by-Reference geht in C++ mit - genau - Referenztypen!

Schreibweise:
int& i

Das ist eine Referenz auf ein int, kein int. Die Umwandlung ist implizit. Ok, das war mir nicht bekannt.

Allerdings finde ich dann die Schreibweise "i = i + 1;" sehr verwirrend. Hardware-mäßig betrachtet ist eine Referenz ein Zeiger und damit eine Variable, die eine Adresse enthält. "i = i + 1;" klingt für mich so, als ob diese Adresse inkrementiert wird und nicht der referenzierte Wert.

Naja, C++ ... ;)

stabilo_boss13
2003-03-11, 08:59:12
Aussage eines befreundeten Informatik-Professors (@GloomY: Universität!):
(hoffe, dass ich das Telefongespräch korrekt zusammengefasst habe)

Die Regeln nach Ansi C++ sind wie folgt:

Die unären Operatoren (z.B. Dereferenzierung, Inkrement, Dekrement usw.) liegen in der Priortätsreihenfolge vor den binären Operatoren (z.B. Multiplikation, Addition, Bitweises OR usw.).

Also müsste

int a = 1;
int b = a++ * a++;

wie folgt aufgelöst werden:
a++ (egal welches, da die Reihenfolge der Auswertung der Ausdrücke hier undefiniert ist)
a wird inkrementiert, aber der vorherige Wert zurückgegeben.
a war vorher 1.
a ist jetzt 2, der zurückgegebene Wert ist 1.

Dann das zweite a++:
a wird inkrementiert, aber der vorherige Wert zurückgegeben.
a war vorher 2.
a ist jetzt 3, der zurückgegebene Wert ist 2.

Also stellt sich der Ausdruck wie folgt dar:
b = 2 * 1 oder b = 1 * 2

Das korrekte Ergebnis wäre also 2!
Warum wäre?

Die Reihenfolge der Auswertung der Ausdrücke ist nach Ansi C++ Standard i.d.R. undefiniert.
Das erklärt, warum das Verhalten der folgenden Ausdrücke teilweise undefiniert ist:

i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // `i' becomes 9
i = ++i + 1; // the behavior is undefined
i = i + 1; // the value of 'i' is incremented


Deshalb sollte man unbedingt vermeiden, eine Variable, die in einem Ausdruck mehrfach vorkommt, auch mit mehreren Inkrement-Operatoren zu versehen. Das Ergebnis kann dann schnell unvorhersagbar werden.

Das Verhalten des Ausdrucks

int b = a++ * a++;

ist also nach Ansi C++ undefiniert und sollte (darf) deshalb nicht verwendet werden.

GloomY
2003-03-11, 13:13:25
Originally posted by stabilo_boss13
Aussage eines befreundeten Informatik-Professors (@GloomY: Universität!):
(hoffe, dass ich das Telefongespräch korrekt zusammengefasst habe)

Die Regeln nach Ansi C++ sind wie folgt:

Die unären Operatoren (z.B. Dereferenzierung, Inkrement, Dekrement usw.) liegen in der Priortätsreihenfolge vor den binären Operatoren (z.B. Multiplikation, Addition, Bitweises OR usw.).

Also müsste

int a = 1;
int b = a++ * a++;

wie folgt aufgelöst werden:
a++ (egal welches, da die Reihenfolge der Auswertung der Ausdrücke hier undefiniert ist)
a wird inkrementiert, aber der vorherige Wert zurückgegeben.
a war vorher 1.
a ist jetzt 2, der zurückgegebene Wert ist 1.

Dann das zweite a++:
a wird inkrementiert, aber der vorherige Wert zurückgegeben.
a war vorher 2.
a ist jetzt 3, der zurückgegebene Wert ist 2.

Also stellt sich der Ausdruck wie folgt dar:
b = 2 * 1 oder b = 1 * 2

Das korrekte Ergebnis wäre also 2!
Warum wäre?

Die Reihenfolge der Auswertung der Ausdrücke ist nach Ansi C++ Standard i.d.R. undefiniert.
Das erklärt, warum das Verhalten der folgenden Ausdrücke teilweise undefiniert ist:

i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // `i' becomes 9
i = ++i + 1; // the behavior is undefined
i = i + 1; // the value of 'i' is incremented
Das ist das, was ich die ganze Zeit sage ;)
Originally posted by stabilo_boss13
Deshalb sollte man unbedingt vermeiden, eine Variable, die in einem Ausdruck mehrfach vorkommt, auch mit mehreren Inkrement-Operatoren zu versehen. Das Ergebnis kann dann schnell unvorhersagbar werden.

Das Verhalten des Ausdrucks

int b = a++ * a++;

ist also nach Ansi C++ undefiniert und sollte (darf) deshalb nicht verwendet werden. Partielle Zustimmung. Das Ergebnis ist in beiden Fällen, dass b=2 und a=3 ist. Daher ist es nicht undefiniert, sondern nimmt ganz diskrete Werte an (in beiden Fällen kommt das gleiche raus.)
Allerdings wäre das Ergebnis deines Beispiels

i = ++i + 1;
wie erwähnt eben nicht definert, weil es eben darauf an kommt, wann man das Increment ausführt.
Ansonsten: Zustimmung =)

Xmas
2003-03-11, 13:26:14
Originally posted by GloomY
Ok, das war mir nicht bekannt.

Allerdings finde ich dann die Schreibweise "i = i + 1;" sehr verwirrend. Hardware-mäßig betrachtet ist eine Referenz ein Zeiger und damit eine Variable, die eine Adresse enthält. "i = i + 1;" klingt für mich so, als ob diese Adresse inkrementiert wird und nicht der referenzierte Wert.

Naja, C++ ... ;)
Das besondere an Referenztypen ist ja, dass sie syntaktisch mit den Werttypen identisch sind.

Das ist übrigens nichts C++-spezifisches, Referenztypen gibt es auch in Delphi, VB, C#, Java, etc., allerdings ist da das Verhalten ein wenig anders.

ethrandil
2003-03-16, 14:47:09
Originally posted by zeckensack
//Da könntsch ausrastn!!!!11 :jedifire:
for (int i=0;i<10;i++)
{
<...>
}
hmm ...

for(int i=10;i-->0; ){
<...>
}

Find ich auch beser ;)

Darkstar
2003-03-16, 18:30:07
Originally posted by zeckensack
Habe ich schon erwähnt, das ich Postfix-Inkrement hasse, und jeden schlagen könnte der sowas macht?
//Da könntsch ausrastn!!!!11 :jedifire:
for (int i=0;i<10;i++)
{
<...>
} Ich habe C und C++ nun wirklich nicht gern, aber irgendwie kann ich hier kein Problem entdecken (in Delphi arbeitet die for-to-do-Schleife schließlich genauso). Was würdest Du denn anders machen (und warum)?

Und bitte nicht schlagen! :bad1:

zeckensack
2003-03-16, 18:43:21
Originally posted by Darkstar
Ich habe C und C++ nun wirklich nicht gern, aber irgendwie kann ich hier kein Problem entdecken (in Delphi arbeitet die for-to-do-Schleife schließlich genauso). Was würdest Du denn anders machen (und warum)?

Und bitte nicht schlagen! :bad1:
for (int i=0;i<10;++i)
{
<...>
}Kleiner, feiner Unterschied ;)

Darkstar
2003-03-16, 21:37:02
Die Schleife mit dem Postfix-Inkrement wird 10 Mal durchlaufen (i = 0 bis 9). Bei dem Beispiel mit dem Präfix-Inkrement wird die Schleife jetzt nur noch 9 Mal durchlaufen (i = 1 bis 9) oder irre ich mich da? ???

Xmas
2003-03-17, 01:30:34
Originally posted by Darkstar
Die Schleife mit dem Postfix-Inkrement wird 10 Mal durchlaufen (i = 0 bis 9). Bei dem Beispiel mit dem Präfix-Inkrement wird die Schleife jetzt nur noch 9 Mal durchlaufen (i = 1 bis 9) oder irre ich mich da? ???
Ja, du irrst. Funktional besteht da gar kein Unterschied. Ich weiß jetzt auch nicht, was du dagegen einzuwenden hast, zeckensack ???

zeckensack
2003-03-17, 02:54:21
Originally posted by Xmas

Ja, du irrst. Funktional besteht da gar kein Unterschied. Ich weiß jetzt auch nicht, was du dagegen einzuwenden hast, zeckensack ??? Na, wie wir im Verlauf dieses Threads gesehen haben sollten, ist Postfix-Inkrement Teufelswerk und gehört verboten
:grhargh:

... man sollte es sich zumindest nicht zu stark angewöhnen. Ich benutze es nach Möglichkeit nie. Wenn, dann nur aus absoluter Faulheit, aber das ist sowieso keine Tugend für einen Programmierer.

ZBubyte* wurz=some_string;
ubyte* knurz=some_other_string;
//copy string
for (int i=0;i<copy_size;++i) *(wurz++)=*(knurz++);
*wurz=0; //terminate string


Wenn man vorher ein bisschen nachdenkt, kann man das ebensogut so schreibenubyte* wurz=some_string;
ubyte* knurz=some_other_string;
//copy string
int i;
for (i=0;i<copy_size;++i) wurz[i]=knurz[i];
wurz[i]=0; //terminate string


Ist IMO sogar ein wenig leichter lesbar.

Demirug
2003-03-17, 07:37:05
zeckensack, das man nicht "Pointerman" spielen soll ist ja ein löblicher tip nur verstehe ich immer noch nicht was das nun mit dem Postfix inkrement bei Schleifen zu tun hat? Dort macht es absolute gar keinen Unterschied ob man den Post oder Prefix benutzt.

zeckensack
2003-03-17, 10:22:54
Originally posted by Demirug
zeckensack, das man nicht "Pointerman" spielen soll ist ja ein löblicher tip nur verstehe ich immer noch nicht was das nun mit dem Postfix inkrement bei Schleifen zu tun hat? Dort macht es absolute gar keinen Unterschied ob man den Post oder Prefix benutzt. Exakt, es macht keinen Unterschied. Und da wir ja sowieso gerade dabei sind, uns dieses Postfix-Inkrement ... Teufelswerk! abzugewöhnen, fangen wir am bestem beim Schleifenzähler damit an :|

ethrandil
2003-03-17, 10:36:00
Korintenkacker :P
Freak :P
'Sack' :P
Typisch :bäh:

naja, vielleicht versuch ichs mir abzugewöhnen ... und meinem Informatiklehrer auch *g*

liquid
2003-03-17, 20:49:07
Hmm, nochmal zurück aufs eigentlich Thema. Es ist doch schneller (besonders im Gleitkommabereich) eine Multiplikation durchzuführen als eine Division zu veranstalten.

Also wäre ein x *= 0.5f doch besser als ein x /= 2.0f oder optimiert der Compiler sowas wech??

cya
liquid

Xmas
2003-03-17, 22:57:28
Originally posted by liquid
Also wäre ein x *= 0.5f doch besser als ein x /= 2.0f oder optimiert der Compiler sowas wech??

Beim Optimieren von Operationen mit Konstanten holen moderne Compiler fast immer das Optimum heraus. Darüber brauchst du dir keine Sorgen zu machen.

aths
2003-03-27, 08:01:01
Was ist nun der Unterschied zwischen

for (i=0,i<5;i++)

und

for (i=0;i++<5;)

?

Es muss einen geben. Bei Variante 1 läuft mein Programm falsch, bei Variante 2 hingegen korrekt.

zeckensack
2003-03-27, 08:13:10
Originally posted by aths
Was ist nun der Unterschied zwischen

for (i=0;i<5;i++)

und

for (i=0;i++<5; )

?

Es muss einen geben. Bei Variante 1 läuft mein Programm falsch, bei Variante 2 hingegen korrekt.

Bei Variante 2 wird i von 1 bis 5 durchgezählt (aus der Sicht des Schleifenkörpers).
Variante 1 geht von 0 bis 4.

#2 ist eigentlich komplett abwegig, du hättest nicht auf XMas hören sollen :naughty:
Der eigentliche Streitfall ist dieses, und das ist wirklich äquivalent
for (i=0;i<5;++i)
vs
for (i=0;i<5;i++)

liquid
2003-03-27, 13:45:25
So, wenn der Thread schonmal hochgepusht wird, dann will ich auch mal meine drängende Frage loswerden.
Habe mir bei meinen letzten Schleifenkörper auch den zbag-Syntax *g* (++i) angeeignet, würde jetzt aber wirklich gerne wissen, was das genau bringt?
Oder ist das genauso wie bei der ungarischen Notation? Der eine mags halt so, der eine nicht? I'm confused... ?-)

cya
liquid

zeckensack
2003-03-27, 14:27:58
Originally posted by liquid
So, wenn der Thread schonmal hochgepusht wird, dann will ich auch mal meine drängende Frage loswerden.
Habe mir bei meinen letzten Schleifenkörper auch den zbag-Syntax *g* (++i) angeeignet, würde jetzt aber wirklich gerne wissen, was das genau bringt?
Oder ist das genauso wie bei der ungarischen Notation? Der eine mags halt so, der eine nicht? I'm confused... ?-)

cya
liquid Postfix-Inkrement ist pure Verwirrung. Das ganze hat sich aus mir völlig unerklärlichen Gründen historisch eingebürgert, deswegen findet es sich in etlichen Programmierbeispielen.

Bei 'komplexen' Datentypen erzeugt es außerdem einen gewissen Overhead, weil eine temporäre Kopie erzeugt werden muß. In 99% der Fälle wird Postfix-Inkrement unnötig benutzt, von daher ist dieser Overhead die pure Verschwendung. Wenn ich eine Klasse schreibe, dann definiere ich erst gar kein Postfix-Inkrement ... die Kopiererei soll der Benutzer der Klasse doch bitteschön selbst erledigen.

Man vergleiche//prefix-increment
some_member=some_member+1;
return(*this);
//postfix-increment is teh suq
Type tmp=*this; //copy constructor for nothing ...
some_member=some_member+1;
return(tmp);

aths
2003-03-28, 22:26:07
Originally posted by zeckensack
Bei Variante 2 wird i von 1 bis 5 durchgezählt (aus der Sicht des Schleifenkörpers).
Variante 1 geht von 0 bis 4. :bonk: Stümmt genau. Ich schreibe in Zukunft: for (int i=0; i<5; ++i) :)