C
muli schrieb:
Trotz allem frag ich mich warum meine Methode Funktioniert!
Ich schreibe mal lieber auf, wo Probleme entstehen können. Ich splitte die einzelnen Vorgänge deshalb mal auf, aus
(MeineKlasse*)(*(int*)p)
wird damit
int* q = static_cast< int* >( p ); // (1)
int& i = *q; // (2)
int address = i; // (3)
MeineKlasse* r = reinterpret_cast< MeineKlasse* >( address ); // (4)
(1) ist undefiniert, falls p nicht hinreichend ausgerichtet für int* ist. Auf einem PC ist das allerdings häufig unproblematisch und auch generell ist zu erwarten, dass Zeigerobjekte wenigstens die Ausrichtung eines ints benötigen.
(2) ist unproblematisch, da wir wissen, dass p tatsächlich auf ein Objekt zeigt (wenn auch vom falschen Typ)
(3) Hier geht es darum, dass von der Stelle i ein int gelesen wird, um den Cast durchführen zu können. Das verletzt die Aliasing-Regeln (3.10/15), da das tatsächlich an dieser Stelle existierende Objekt ein MeineKlasse* ist - somit undefiniertes Verhalten. Was vermutlich erwartet wird, ist, dass der gelesene Wert dem an dieser Stelle stehenden Speicherinhalt entspricht (und das kann mit viel Glück auch so sein - irgendwann schreib ich mal was für die faq), also das etwas passiert, dass äquivalent zu
int address; memcpy( &address, &i, sizeof address );
ist. Zudem muss dieser Speicherinhalt natürlich noch einem gültigen int-Wert entsprechen - auf exotischer Hardware könnte es hier zu traps kommen, aber das ist ein weniger bedeutsames Detail.
(4) ist unproblematisch, sofern die entsprechende Plattform über diesen Cast verfügt und dieser einigermaßen das tut, was man an dieser Stelle erwartet. Damit das am Ende äquivalent zu der korrekten Form
*static_cast< MeineKlasse** >( p )
ist, muss zusätzlich noch die Bedingung erfüllt sein, dass die Repräsentation der beteiligten Typen gleich ist, also
int i = ...
foo* p = reinterpret_cast< foo* >( i );
assert( sizeof i == sizeof p );
assert( memcmp( &i, &p, sizeof i ) == 0 );
Das klapp auf einem PC bei 32-bit zufällig, im Allgemeinen kann es ganz anders sein.