Seltsamer Fehler beim Herumspielen mit reinterpret_cast
-
Hallo,
ich habe mich ein wenig mit reinterpret_cast beschäftigt. Dabei wollte ich einen einfachten Code schreiben, der mit die unteren 32 Bit einer long long variablen liefert:typedef unsigned long long ull; typedef unsigned int ui; int main() { ull b = 13; ui a = *reinterpret_cast<const ui* const>(&b); //ausgabe: 30 }Dabei erhält a den falschen Wert (30 statt 13) und es gibt eine Warnung:
7: warning: dereferencing type-punned pointer will break strict-aliasing rulesWas will mir die Warnung sagen? Was mache ich falsch?
Schonmal Danke für alle Antworten!
-
Hi,
das ist ein Bug (?) des GCC in neueren Versionen. Die Konvertierung ist erlaubt und wird in der Praxis keine Probleme bereiten.Siehe: http://wiki.alliedmods.net/Metamod:Source_Development#Linux
-fno-strict-aliasing - By default, GCC does not allow certain type casts which were perfectly legal in previous versions, and are perfectly legal in almost every other C/C++ compiler. These type casts are prevalent and without this option, GCC will generate incorrect code.
-
NeedHelpPlease schrieb:
Was mache ich falsch?
Dass du dazu auf
reinterpret_castzurückgreifst. Das will dir zwar die Warnung nicht sagen, aber sage ich
unsigned long long b = 13; unsigned long a = b & 0xFFFFFFFF;Was in deinem Fall genau herauskommt, ist im Standard nicht definiert. Bei den meisten Kompiler wird es wohl funktionieren. Allerdings könntest du auch Probleme mit Systemen bekommen, wo Big Endian in Verwendung ist.
Mein Code ist vollständig definiert. Naja, bis darauf das long long erst im nächsten Standard kommt und die Grössen der Variablen nicht genau definiert ist, aber das ist in deinem Code auch der Fall. Gehen wir daher davon aus, dass es 64 Bit und 32 Bit vorzeichenlose Zahlen sind (;)). Unter dieser Annahme liefert es auch immer die unteren 32 Bit, egal ob dein System nun Big-Endian oder Little-Endian verwendet.Aber das könnte man alles noch als Erbsenzählerei hinsetzen, was meiner Meinung nach wichtiger ist, mein Code kann man deutlich besser lesen und man versteht sofort, was gemacht wird.
Grüssli
-
Dravere schrieb:
...
vs
theliquidwave schrieb:
...
Auf welche Antwort kann man sich nun verlassen?
-
WerHatNunRecht? schrieb:
Auf welche Antwort kann man sich nun verlassen?
Beide nicht.
http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
-
volkard schrieb:
WerHatNunRecht? schrieb:
Auf welche Antwort kann man sich nun verlassen?
Beide nicht.
http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.htmlDa musst du mir aber zuerst mal erklären, was an meinem Beitrag nicht stimmt. Ich umgehe dieses strict aliasing komplett, indem ich gar nicht mit Zeiger herumhantiere.
Grüssli
-
Dravere schrieb:
Da musst du mir aber zuerst mal erklären, was an meinem Beitrag nicht stimmt.
Die Behaptung, es läge am bösen reinterpret_cast.
Und die Nahelegung, die Endianess sei das Hauptproblem.
-
volkard schrieb:
Dravere schrieb:
Da musst du mir aber zuerst mal erklären, was an meinem Beitrag nicht stimmt.
Die Behaptung, es läge am bösen reinterpret_cast.
Und die Nahelegung, die Endianess sei das Hauptproblem.Dann hast du meinen Beitrag völlig falsch verstanden. Ich habe mich sogar explizit von der Warnung distanziert. Und mit dem Endian-Problem wollte ich auf ein anderes Problem hinweisen.
Mir ging es eher darum, dass man sich nicht mit solchen Dingen auseinandersetzen sollte, wenn man es doch ganz einfach und wohl definiert machen kann.
reinterpret_castist laut Standard in diesem Fall nun mal nicht exakt definiert. Wieso also denreinterpret_castverwenden, wenn man es einfach, verständlich und korrekt machen kann?Grüssli
-
Dravere schrieb:
volkard schrieb:
Dravere schrieb:
Da musst du mir aber zuerst mal erklären, was an meinem Beitrag nicht stimmt.
Die Behaptung, es läge am bösen reinterpret_cast.
Und die Nahelegung, die Endianess sei das Hauptproblem.Dann hast du meinen Beitrag völlig falsch verstanden.
Ja, anscheinend.
Dravere schrieb:
Mir ging es eher darum, dass man sich nicht mit solchen Dingen auseinandersetzen sollte, wenn man es doch ganz einfach und wohl definiert machen kann.
Ah, dem kann ich natürlich nicht zustimmen. Natürlich muß man auch das lernen. Und dann nicht benutzen.
Dravere schrieb:
reinterpret_castist laut Standard in diesem Fall nun mal nicht exakt definiert. Wieso also denreinterpret_castverwenden, wenn man es einfach, verständlich und korrekt machen kann?Ich glaube, daß der reinterpret_cast hier aber sauber funktioniert.
Versuche mitcout<<reinterpret_cast<const ui* const>(&b)weisen sogar ein wenig in diese Richtung.
Vielleicht erzeugt erst das Auswerten mit * den Müll. Denselben Müll kann man auch ohne reinterpret_cast erzeugen, zum Beispiel mit dieser union mit den beiden Zeigern drin.
-
volkard schrieb:
Ah, dem kann ich natürlich nicht zustimmen. Natürlich muß man auch das lernen. Und dann nicht benutzen.
Gut, da hast du natürlich recht. Deswegen habe ich den Link auch durchgelesen und fand den Inhalt sehr interessant. Aber ich hätte es wohl gar nie so gemacht, wie es der Threadersteller gemacht hat

volkard schrieb:
Ich glaube, daß der reinterpret_cast hier aber sauber funktioniert.
Versuche mitcout<<reinterpret_cast<const ui* const>(&b)weisen sogar ein wenig in diese Richtung.
Vielleicht erzeugt erst das Auswerten mit * den Müll. Denselben Müll kann man auch ohne reinterpret_cast erzeugen, zum Beispiel mit dieser union mit den beiden Zeigern drin.Ja, wenn man pingelig sein will, dann ist erst der Dereferenzierungsoperator schuld. Es ist nämlich wohldefiniert, wenn man etwas in einen anderen Zeiger umbiegt, es wieder zurückbiegt und dann darauf zugreift. Also an einem Beispiel:
int a; char* b = reinterpret_cast<char*>(&a); int* p = reinterpret_cast<int*>(b); *p = 10; // <- klar definiert und korrekt.Es ist nur nicht definiert, was passiert, wenn man auf
bzugreift. Aber leider wirdreinterpret_castoft dazu verwendet, genau dies zu erreichen, was der Threadersteller will. Weshalb man diese Unsitte nach dem sehr klar ersichtlichenreinterpret_castbenennt, während der tatsächliche Übeltäter, wegen seiner Unscheinbarheit ungeschoren davon kommt ...
Grüssli