Call by Reference TypeCast Verständnis
-
Ich übergebe einer Funktion eine Addresse eines Pointers.
Den ich ungefähr so angelegt habe:MeineKlasse *PointerNun übergebe ich den folgendermaßen meiner Funktion:
void Funktion(&Pointer)Die Funktion übernimmt die addresse als void*
Wenn ich nun die Daten aus der Klasse in der Funktion erreichen möchte muss ich den
dereferenzieren und casten:Funktion(void* p) { //so funktioniert es! aber warum? ((MeineKlasse*)(*(int*))->... }Warum muss ich in einen int* casten wenn ich void * mache funktioniert das nicht?
Wenn ich das schon so mache müsste ich dann nicht in UINT* casten?Gibts da nicht ne bessere Lösung?
muli
-
Was willst du da machen? Warum nimmt deine Funktion nicht einfach nen Pointer auf deine Klasse?
-
muli schrieb:
Gibts da nicht ne bessere Lösung?
Ja, nicht mit void* arbeiten... Damit gibst Du jede Typsicherheit auf. Theoretisch könnte man beliebigen Datenmüll übergeben.
Damit verlagerst Du vor allem Compilerfehler (z.B. falscher Typ übergeben = Fehlermeldung vom Compiler) in Laufzeitfehler die dann zum Absturz des Programms führen -> very bad idea.
-
äh: Die Funktion ist ein Konstruktor. Die Klasse soll einen Zeiger auf die andere Klasse haben. Eine Instanz ist aber nicht immer schon bei Instanzierung geschaffen. deshalb kann ich keinen Zeiger übergeben. Aber die Adresse eines Zeiges!
loks: Die Frage war:
Warum muss ich eine Speicheraddresse in ein Int casten bevor ich dann ins richtige caste?
Ich "zeige" niemals auf einen Int!
Warum funktioniert es nicht wenn ich einen void* verwende?Hoffe man kann verstehen was ich meine wenn nicht sagt mir bescheid dann versuch ich das alles nochmal umzuformulieren
schonmal danke für eure Bemühungenmuli
-
muli schrieb:
dereferenzieren und casten:
umgekehrt, schließlich hast du ursprünglich zuerst den Pointer ermittelt, der anschließend implizit in void* konvertiert wurde. Eine Aktion machen wir im Allgemeinen dadurch rückgängig, dass wir die jeweils inversen Einzeloperationen in umgekehrter Reihenfolge durchführen. Der korrekte Weg wäre daher
(*static_cast<MeineKlasse**>(p)->Nicht, dass ich erkennen kann, weshalb du nicht gleich MeineKlasse** als Parametertyp der Funktion verwendest.
-
Ja da hast du recht! Vorallem das mit dem ** ist natürlich besser. Danke!
Trotz allem frag ich mich warum meine Methode Funktioniert!Danke an alle die versucht haben zu helfen.
muli
-
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 zuint 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.