Ich schreibe gerade ein kleines Programm zum einlesen von Wavefront OBJ-Dateien (speichert 3D Geometrie). Dazu verwende ich einen STL Vektor zum speichern der Vertices. Das kranke daran ist jetzt, dass mir der Indexoperator ([]), die korrekten Daten liefert, der Iterator hingeben nicht! Vielleicht ein GCC Bug in der aktuellen Version? (gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1)
Im Internet hab ich diesbezüglich jedenfalls rein gar nichts gefunden.
Hier ist der relevante Codeschnipsel: ```for (unsigned int i = 0; i < v.size(); i += 3)
{
printf("v %f %f %f
“, v**, v[i+1], v[i+2]);
}
printf(”
");
for (std::vector::iterator it = v.begin(); it != v.end(); ++it)
{
printf("v %f %f %f
", *it, *(++it), *(++it));
}```
Die Ausgabe ist folgende:
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -0.999999 -0.999999 1.000000
v 1.000001 1.000001 1.000000
v 1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
Die obere Ausgabe ist vollkommen korrekt, die untere hingegen reiner Schrott. Es sind zwar sehr ähnliche Werte, aber eben doch nicht diesselben. Es kann auch nicht einfach nur an der Reihenfolge liegen, sonst gäbe es bei dem unteren Listing nicht 2x -0.999999 sondern nur einmal! Hab’s auch schon mit anderne Dateien probiert, immer dasselbe.
hmmm ich hab damit noch nicht gearbeitet, aber mein Vorschlag wäre, das du mal andere Werte als -1 und 1 einträgst
weil wenn du 1, 2, 3, 4,… benutzt siehst du besser ob die Reihenfolge nicht passt oder ob er völligen Müll anzeigt
Hmja, hast du mal EagleEye’s Vorschlag probiert? Es erscheint unwahrscheinlich, dass der GCC bei so etwas elementarem einen Bug hat. Ggf. mal an einem KSKB testen.
Das ist der iterator, der da mit
std::vector::iterator it
deklariert ist (das *it ist dann der inhalt des Iterators - also die eigentlichen GLfloat-Werte)
Da fällt mir auf: Die Schreibweise an sich erscheint mir (zurückhaltend formuliert) „gefährlich“: Ich würde nicht darauf wetten, dass die Auswertungsreihenfolge bei
printf("v %f %f %f
", *it, *(++it), *(++it));
so ist, wie man intuitiv denken würde (oder hofft) : Wenn die präinkrement-Operatoren VOR den Dereferenzierungen ausgeführt werden, könnte da was ziemlich konfuses rauskommen. Sicherheitshalber würde ich es mal als
schreiben, und … naja… Ich versuche grundsätzlich Code zu vermeiden, wo der Unterschied zwischen prä- und postinkrement relevant ist… Lieber zwei eindeutige Zeilen als eine zweideutige
Danke Marco13, so hat es jetzt funktioniert. Offenbar ist der Unterschied zwischen Post- und Präinkrement (zumindest in C/C++) eher kosmetischer Natur.
Aber da ja mittlerweile C++11 offiziell verabschiedet wurde, habe ich mich für jene elegantere Lösung entschieden: for (GLfloat& f : v) { ... }
Naja - kosmetisch nicht. Im Gegenteil, der ist klar spezifiziert und hat auch seinen Zweck:
int a = 3;
int b = ++a; // a wird erhöht und dann ausgewertet
// Jetzt ist b==4 und a==4
int c = a++; // a wird erst ausgewertet und dann erhöht
// Jetzt ist c==4 und a==5
Aber beim ‚printf‘ wird ja die ‚ellipse‘ verwendet - also dieses va_args für beliebig viele Argumente. Und ich wüßte spontan nicht (und auch nicht, ob überhaupt verbindlich spezifiziert ist) was bei sowas wie
int a = 3;
printf("%d %d %d
", a, ++a, a++);
ausgegeben wird. Man könnte meinen, es müßte „3 4 4“ sein, aber … vielleicht auch nicht. Und durch die Dereferenzierungen beim Iterator wird das noch heikler (und undurchschaubarer). Aber es gibt ja Möglichkeiten, es so zu machen, dass man sicher sein kann, was rauskommt
[QUOTE=Marco13]Da fällt mir auf: Die Schreibweise an sich erscheint mir (zurückhaltend formuliert) “gefährlich”: Ich würde nicht darauf wetten, dass die Auswertungsreihenfolge bei
printf("v %f %f %f
", *it, *(++it), *(++it));
so ist, wie man intuitiv denken würde[/QUOTE]
Ist es auch nicht, das darf jeder Compiler so halten wie er es für richtig hält.
Kommaoperatoren können in einer beliebigen Reihenfolge aufgelöst werden. Von vorne nach hinten, von hinten nach vorne oder irgendwie quer-mitten-durch.